xref: /csrg-svn/sys/kern/kern_descrip.c (revision 53466)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  *
7  *	@(#)kern_descrip.c	7.31 (Berkeley) 05/13/92
8  */
9 
10 #include "param.h"
11 #include "systm.h"
12 #include "filedesc.h"
13 #include "kernel.h"
14 #include "vnode.h"
15 #include "proc.h"
16 #include "file.h"
17 #include "socket.h"
18 #include "socketvar.h"
19 #include "stat.h"
20 #include "ioctl.h"
21 #include "fcntl.h"
22 #include "malloc.h"
23 #include "syslog.h"
24 #include "resourcevar.h"
25 
26 /*
27  * Descriptor management.
28  */
29 struct file *filehead;	/* head of list of open files */
30 int nfiles;		/* actual number of open files */
31 
32 /*
33  * System calls on descriptors.
34  */
35 /* ARGSUSED */
36 getdtablesize(p, uap, retval)
37 	struct proc *p;
38 	struct args *uap;
39 	int *retval;
40 {
41 
42 	*retval = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
43 	return (0);
44 }
45 
46 /*
47  * Duplicate a file descriptor.
48  */
49 /* ARGSUSED */
50 dup(p, uap, retval)
51 	struct proc *p;
52 	struct args {
53 		int	i;
54 	} *uap;
55 	int *retval;
56 {
57 	register struct filedesc *fdp = p->p_fd;
58 	struct file *fp;
59 	int fd, error;
60 
61 	/*
62 	 * XXX Compatibility
63 	 */
64 	if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); }
65 
66 	if ((unsigned)uap->i >= fdp->fd_nfiles ||
67 	    (fp = fdp->fd_ofiles[uap->i]) == NULL)
68 		return (EBADF);
69 	if (error = fdalloc(p, 0, &fd))
70 		return (error);
71 	fdp->fd_ofiles[fd] = fp;
72 	fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE;
73 	fp->f_count++;
74 	if (fd > fdp->fd_lastfile)
75 		fdp->fd_lastfile = fd;
76 	*retval = fd;
77 	return (0);
78 }
79 
80 /*
81  * Duplicate a file descriptor to a particular value.
82  */
83 /* ARGSUSED */
84 dup2(p, uap, retval)
85 	struct proc *p;
86 	struct args {
87 		u_int	from;
88 		u_int	to;
89 	} *uap;
90 	int *retval;
91 {
92 	register struct filedesc *fdp = p->p_fd;
93 	register struct file *fp;
94 	register u_int old = uap->from, new = uap->to;
95 	int i, error;
96 
97 	if (old >= fdp->fd_nfiles ||
98 	    (fp = fdp->fd_ofiles[old]) == NULL ||
99 	    new >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
100 		return (EBADF);
101 	*retval = new;
102 	if (old == new)
103 		return (0);
104 	if (new >= fdp->fd_nfiles) {
105 		if (error = fdalloc(p, new, &i))
106 			return (error);
107 		if (new != i)
108 			panic("dup2: fdalloc");
109 	} else if (fdp->fd_ofiles[new]) {
110 		if (fdp->fd_ofileflags[new] & UF_MAPPED)
111 			(void) munmapfd(p, new);
112 		/*
113 		 * dup2() must succeed even if the close has an error.
114 		 */
115 		(void) closef(fdp->fd_ofiles[new], p);
116 	}
117 	fdp->fd_ofiles[new] = fp;
118 	fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
119 	fp->f_count++;
120 	if (new > fdp->fd_lastfile)
121 		fdp->fd_lastfile = new;
122 	return (0);
123 }
124 
125 /*
126  * The file control system call.
127  */
128 /* ARGSUSED */
129 fcntl(p, uap, retval)
130 	struct proc *p;
131 	register struct args {
132 		int	fd;
133 		int	cmd;
134 		int	arg;
135 	} *uap;
136 	int *retval;
137 {
138 	register struct filedesc *fdp = p->p_fd;
139 	register struct file *fp;
140 	register char *pop;
141 	struct vnode *vp;
142 	int i, tmp, error, flg = F_POSIX;
143 	struct flock fl;
144 
145 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
146 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
147 		return (EBADF);
148 	pop = &fdp->fd_ofileflags[uap->fd];
149 	switch(uap->cmd) {
150 	case F_DUPFD:
151 		if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
152 			return (EINVAL);
153 		if (error = fdalloc(p, uap->arg, &i))
154 			return (error);
155 		fdp->fd_ofiles[i] = fp;
156 		fdp->fd_ofileflags[i] = *pop &~ UF_EXCLOSE;
157 		fp->f_count++;
158 		if (i > fdp->fd_lastfile)
159 			fdp->fd_lastfile = i;
160 		*retval = i;
161 		return (0);
162 
163 	case F_GETFD:
164 		*retval = *pop & 1;
165 		return (0);
166 
167 	case F_SETFD:
168 		*pop = (*pop &~ 1) | (uap->arg & 1);
169 		return (0);
170 
171 	case F_GETFL:
172 		*retval = OFLAGS(fp->f_flag);
173 		return (0);
174 
175 	case F_SETFL:
176 		fp->f_flag &= ~FCNTLFLAGS;
177 		fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
178 		tmp = fp->f_flag & FNONBLOCK;
179 		error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
180 		if (error)
181 			return (error);
182 		tmp = fp->f_flag & FASYNC;
183 		error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
184 		if (!error)
185 			return (0);
186 		fp->f_flag &= ~FNONBLOCK;
187 		tmp = 0;
188 		(void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
189 		return (error);
190 
191 	case F_GETOWN:
192 		if (fp->f_type == DTYPE_SOCKET) {
193 			*retval = ((struct socket *)fp->f_data)->so_pgid;
194 			return (0);
195 		}
196 		error = (*fp->f_ops->fo_ioctl)
197 			(fp, (int)TIOCGPGRP, (caddr_t)retval, p);
198 		*retval = -*retval;
199 		return (error);
200 
201 	case F_SETOWN:
202 		if (fp->f_type == DTYPE_SOCKET) {
203 			((struct socket *)fp->f_data)->so_pgid = uap->arg;
204 			return (0);
205 		}
206 		if (uap->arg <= 0) {
207 			uap->arg = -uap->arg;
208 		} else {
209 			struct proc *p1 = pfind(uap->arg);
210 			if (p1 == 0)
211 				return (ESRCH);
212 			uap->arg = p1->p_pgrp->pg_id;
213 		}
214 		return ((*fp->f_ops->fo_ioctl)
215 			(fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
216 
217 	case F_SETLKW:
218 		flg |= F_WAIT;
219 		/* Fall into F_SETLK */
220 
221 	case F_SETLK:
222 		if (fp->f_type != DTYPE_VNODE)
223 			return (EBADF);
224 		vp = (struct vnode *)fp->f_data;
225 		/* Copy in the lock structure */
226 		error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
227 		if (error)
228 			return (error);
229 		if (fl.l_whence == SEEK_CUR)
230 			fl.l_start += fp->f_offset;
231 		switch (fl.l_type) {
232 
233 		case F_RDLCK:
234 			if ((fp->f_flag & FREAD) == 0)
235 				return (EBADF);
236 			p->p_flag |= SADVLCK;
237 			return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
238 
239 		case F_WRLCK:
240 			if ((fp->f_flag & FWRITE) == 0)
241 				return (EBADF);
242 			p->p_flag |= SADVLCK;
243 			return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
244 
245 		case F_UNLCK:
246 			return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
247 				F_POSIX));
248 
249 		default:
250 			return (EINVAL);
251 		}
252 
253 	case F_GETLK:
254 		if (fp->f_type != DTYPE_VNODE)
255 			return (EBADF);
256 		vp = (struct vnode *)fp->f_data;
257 		/* Copy in the lock structure */
258 		error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
259 		if (error)
260 			return (error);
261 		if (fl.l_whence == SEEK_CUR)
262 			fl.l_start += fp->f_offset;
263 		if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
264 			return (error);
265 		return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl)));
266 
267 	default:
268 		return (EINVAL);
269 	}
270 	/* NOTREACHED */
271 }
272 
273 /*
274  * Close a file descriptor.
275  */
276 /* ARGSUSED */
277 close(p, uap, retval)
278 	struct proc *p;
279 	struct args {
280 		int	fd;
281 	} *uap;
282 	int *retval;
283 {
284 	register struct filedesc *fdp = p->p_fd;
285 	register struct file *fp;
286 	register int fd = uap->fd;
287 	register u_char *pf;
288 
289 	if ((unsigned)fd >= fdp->fd_nfiles ||
290 	    (fp = fdp->fd_ofiles[fd]) == NULL)
291 		return (EBADF);
292 	pf = (u_char *)&fdp->fd_ofileflags[fd];
293 	if (*pf & UF_MAPPED)
294 		(void) munmapfd(p, fd);
295 	fdp->fd_ofiles[fd] = NULL;
296 	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
297 		fdp->fd_lastfile--;
298 	if (fd < fdp->fd_freefile)
299 		fdp->fd_freefile = fd;
300 	*pf = 0;
301 	return (closef(fp, p));
302 }
303 
304 #ifdef COMPAT_43
305 /*
306  * Return status information about a file descriptor.
307  */
308 /* ARGSUSED */
309 fstat(p, uap, retval)
310 	struct proc *p;
311 	register struct args {
312 		int	fd;
313 		struct	ostat *sb;
314 	} *uap;
315 	int *retval;
316 {
317 	register struct filedesc *fdp = p->p_fd;
318 	register struct file *fp;
319 	struct stat ub;
320 	struct ostat oub;
321 	int error;
322 
323 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
324 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
325 		return (EBADF);
326 	switch (fp->f_type) {
327 
328 	case DTYPE_VNODE:
329 		error = vn_stat((struct vnode *)fp->f_data, &ub, p);
330 		break;
331 
332 	case DTYPE_SOCKET:
333 		error = soo_stat((struct socket *)fp->f_data, &ub);
334 		break;
335 
336 	default:
337 		panic("fstat");
338 		/*NOTREACHED*/
339 	}
340 	cvtstat(&ub, &oub);
341 	if (error == 0)
342 		error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub));
343 	return (error);
344 }
345 #endif /* COMPAT_43 */
346 
347 /*
348  * Return status information about a file descriptor.
349  */
350 /* ARGSUSED */
351 fqstat(p, uap, retval)
352 	struct proc *p;
353 	register struct args {
354 		int	fd;
355 		struct	stat *sb;
356 	} *uap;
357 	int *retval;
358 {
359 	register struct filedesc *fdp = p->p_fd;
360 	register struct file *fp;
361 	struct stat ub;
362 	int error;
363 
364 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
365 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
366 		return (EBADF);
367 	switch (fp->f_type) {
368 
369 	case DTYPE_VNODE:
370 		error = vn_stat((struct vnode *)fp->f_data, &ub, p);
371 		break;
372 
373 	case DTYPE_SOCKET:
374 		error = soo_stat((struct socket *)fp->f_data, &ub);
375 		break;
376 
377 	default:
378 		panic("fstat");
379 		/*NOTREACHED*/
380 	}
381 	if (error == 0)
382 		error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
383 	return (error);
384 }
385 
386 /*
387  * Allocate a file descriptor for the process.
388  */
389 int fdexpand;
390 
391 fdalloc(p, want, result)
392 	struct proc *p;
393 	int want;
394 	int *result;
395 {
396 	register struct filedesc *fdp = p->p_fd;
397 	register int i;
398 	int lim, last, nfiles;
399 	struct file **newofile;
400 	char *newofileflags;
401 
402 	/*
403 	 * Search for a free descriptor starting at the higher
404 	 * of want or fd_freefile.  If that fails, consider
405 	 * expanding the ofile array.
406 	 */
407 	lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
408 	for (;;) {
409 		last = min(fdp->fd_nfiles, lim);
410 		if ((i = want) < fdp->fd_freefile)
411 			i = fdp->fd_freefile;
412 		for (; i < last; i++) {
413 			if (fdp->fd_ofiles[i] == NULL) {
414 				fdp->fd_ofileflags[i] = 0;
415 				if (i > fdp->fd_lastfile)
416 					fdp->fd_lastfile = i;
417 				if (want <= fdp->fd_freefile)
418 					fdp->fd_freefile = i;
419 				*result = i;
420 				return (0);
421 			}
422 		}
423 
424 		/*
425 		 * No space in current array.  Expand?
426 		 */
427 		if (fdp->fd_nfiles >= lim)
428 			return (EMFILE);
429 		if (fdp->fd_nfiles < NDEXTENT)
430 			nfiles = NDEXTENT;
431 		else
432 			nfiles = 2 * fdp->fd_nfiles;
433 		MALLOC(newofile, struct file **, nfiles * OFILESIZE,
434 		    M_FILEDESC, M_WAITOK);
435 		newofileflags = (char *) &newofile[nfiles];
436 		/*
437 		 * Copy the existing ofile and ofileflags arrays
438 		 * and zero the new portion of each array.
439 		 */
440 		bcopy(fdp->fd_ofiles, newofile,
441 			(i = sizeof(struct file *) * fdp->fd_nfiles));
442 		bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
443 		bcopy(fdp->fd_ofileflags, newofileflags,
444 			(i = sizeof(char) * fdp->fd_nfiles));
445 		bzero(newofileflags + i, nfiles * sizeof(char) - i);
446 		if (fdp->fd_nfiles > NDFILE)
447 			FREE(fdp->fd_ofiles, M_FILEDESC);
448 		fdp->fd_ofiles = newofile;
449 		fdp->fd_ofileflags = newofileflags;
450 		fdp->fd_nfiles = nfiles;
451 		fdexpand++;
452 	}
453 }
454 
455 /*
456  * Check to see whether n user file descriptors
457  * are available to the process p.
458  */
459 fdavail(p, n)
460 	struct proc *p;
461 	register int n;
462 {
463 	register struct filedesc *fdp = p->p_fd;
464 	register struct file **fpp;
465 	register int i;
466 
467 	if ((i = p->p_rlimit[RLIMIT_OFILE].rlim_cur - fdp->fd_nfiles) > 0 &&
468 	    (n -= i) <= 0)
469 		return (1);
470 	fpp = &fdp->fd_ofiles[fdp->fd_freefile];
471 	for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)
472 		if (*fpp == NULL && --n <= 0)
473 			return (1);
474 	return (0);
475 }
476 
477 /*
478  * Create a new open file structure and allocate
479  * a file decriptor for the process that refers to it.
480  */
481 falloc(p, resultfp, resultfd)
482 	register struct proc *p;
483 	struct file **resultfp;
484 	int *resultfd;
485 {
486 	register struct file *fp, *fq, **fpp;
487 	int error, i;
488 
489 	if (error = fdalloc(p, 0, &i))
490 		return (error);
491 	if (nfiles >= maxfiles) {
492 		tablefull("file");
493 		return (ENFILE);
494 	}
495 	/*
496 	 * Allocate a new file descriptor.
497 	 * If the process has file descriptor zero open, add to the list
498 	 * of open files at that point, otherwise put it at the front of
499 	 * the list of open files.
500 	 */
501 	nfiles++;
502 	MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
503 	if (fq = p->p_fd->fd_ofiles[0])
504 		fpp = &fq->f_filef;
505 	else
506 		fpp = &filehead;
507 	p->p_fd->fd_ofiles[i] = fp;
508 	if (fq = *fpp)
509 		fq->f_fileb = &fp->f_filef;
510 	fp->f_filef = fq;
511 	fp->f_fileb = fpp;
512 	*fpp = fp;
513 	fp->f_count = 1;
514 	fp->f_msgcount = 0;
515 	fp->f_offset = 0;
516 	fp->f_cred = p->p_ucred;
517 	crhold(fp->f_cred);
518 	if (resultfp)
519 		*resultfp = fp;
520 	if (resultfd)
521 		*resultfd = i;
522 	return (0);
523 }
524 
525 /*
526  * Free a file descriptor.
527  */
528 ffree(fp)
529 	register struct file *fp;
530 {
531 	register struct file *fq;
532 
533 	if (fq = fp->f_filef)
534 		fq->f_fileb = fp->f_fileb;
535 	*fp->f_fileb = fq;
536 	crfree(fp->f_cred);
537 #ifdef DIAGNOSTIC
538 	fp->f_filef = NULL;
539 	fp->f_fileb = NULL;
540 	fp->f_count = 0;
541 #endif
542 	nfiles--;
543 	FREE(fp, M_FILE);
544 }
545 
546 /*
547  * Copy a filedesc structure.
548  */
549 struct filedesc *
550 fdcopy(p)
551 	struct proc *p;
552 {
553 	register struct filedesc *newfdp, *fdp = p->p_fd;
554 	register struct file **fpp;
555 	register int i;
556 
557 	MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
558 	    M_FILEDESC, M_WAITOK);
559 	bcopy(fdp, newfdp, sizeof(struct filedesc));
560 	VREF(newfdp->fd_cdir);
561 	if (newfdp->fd_rdir)
562 		VREF(newfdp->fd_rdir);
563 	newfdp->fd_refcnt = 1;
564 
565 	/*
566 	 * If the number of open files fits in the internal arrays
567 	 * of the open file structure, use them, otherwise allocate
568 	 * additional memory for the number of descriptors currently
569 	 * in use.
570 	 */
571 	if (newfdp->fd_lastfile < NDFILE) {
572 		newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
573 		newfdp->fd_ofileflags =
574 		    ((struct filedesc0 *) newfdp)->fd_dfileflags;
575 		i = NDFILE;
576 	} else {
577 		/*
578 		 * Compute the smallest multiple of NDEXTENT needed
579 		 * for the file descriptors currently in use,
580 		 * allowing the table to shrink.
581 		 */
582 		i = newfdp->fd_nfiles;
583 		while (i > 2 * NDEXTENT && i >= newfdp->fd_lastfile * 2)
584 			i /= 2;
585 		MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
586 		    M_FILEDESC, M_WAITOK);
587 		newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
588 	}
589 	newfdp->fd_nfiles = i;
590 	bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
591 	bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
592 	fpp = newfdp->fd_ofiles;
593 	for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
594 		if (*fpp != NULL)
595 			(*fpp)->f_count++;
596 	return (newfdp);
597 }
598 
599 /*
600  * Release a filedesc structure.
601  */
602 void
603 fdfree(p)
604 	struct proc *p;
605 {
606 	register struct filedesc *fdp = p->p_fd;
607 	struct file **fpp;
608 	register int i;
609 
610 	if (--fdp->fd_refcnt > 0)
611 		return;
612 	fpp = fdp->fd_ofiles;
613 	for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
614 		if (*fpp)
615 			(void) closef(*fpp, p);
616 	if (fdp->fd_nfiles > NDFILE)
617 		FREE(fdp->fd_ofiles, M_FILEDESC);
618 	vrele(fdp->fd_cdir);
619 	if (fdp->fd_rdir)
620 		vrele(fdp->fd_rdir);
621 	FREE(fdp, M_FILEDESC);
622 }
623 
624 /*
625  * Internal form of close.
626  * Decrement reference count on file structure.
627  * Note: p may be NULL when closing a file
628  * that was being passed in a message.
629  */
630 closef(fp, p)
631 	register struct file *fp;
632 	register struct proc *p;
633 {
634 	struct vnode *vp;
635 	struct flock lf;
636 	int error;
637 
638 	if (fp == NULL)
639 		return (0);
640 	/*
641 	 * POSIX record locking dictates that any close releases ALL
642 	 * locks owned by this process.  This is handled by setting
643 	 * a flag in the unlock to free ONLY locks obeying POSIX
644 	 * semantics, and not to free BSD-style file locks.
645 	 * If the descriptor was in a message, POSIX-style locks
646 	 * aren't passed with the descriptor.
647 	 */
648 	if (p && (p->p_flag & SADVLCK) && fp->f_type == DTYPE_VNODE) {
649 		lf.l_whence = SEEK_SET;
650 		lf.l_start = 0;
651 		lf.l_len = 0;
652 		lf.l_type = F_UNLCK;
653 		vp = (struct vnode *)fp->f_data;
654 		(void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
655 	}
656 	if (--fp->f_count > 0)
657 		return (0);
658 	if (fp->f_count < 0)
659 		panic("closef: count < 0");
660 	if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
661 		lf.l_whence = SEEK_SET;
662 		lf.l_start = 0;
663 		lf.l_len = 0;
664 		lf.l_type = F_UNLCK;
665 		vp = (struct vnode *)fp->f_data;
666 		(void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
667 	}
668 	error = (*fp->f_ops->fo_close)(fp, p);
669 	ffree(fp);
670 	return (error);
671 }
672 
673 /*
674  * Apply an advisory lock on a file descriptor.
675  *
676  * Just attempt to get a record lock of the requested type on
677  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
678  */
679 
680 /* ARGSUSED */
681 flock(p, uap, retval)
682 	struct proc *p;
683 	register struct args {
684 		int	fd;
685 		int	how;
686 	} *uap;
687 	int *retval;
688 {
689 	register struct filedesc *fdp = p->p_fd;
690 	register struct file *fp;
691 	struct vnode *vp;
692 	struct flock lf;
693 	int error;
694 
695 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
696 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
697 		return (EBADF);
698 	if (fp->f_type != DTYPE_VNODE)
699 		return (EOPNOTSUPP);
700 	vp = (struct vnode *)fp->f_data;
701 	lf.l_whence = SEEK_SET;
702 	lf.l_start = 0;
703 	lf.l_len = 0;
704 	if (uap->how & LOCK_UN) {
705 		lf.l_type = F_UNLCK;
706 		fp->f_flag &= ~FHASLOCK;
707 		return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
708 	}
709 	if (uap->how & LOCK_EX)
710 		lf.l_type = F_WRLCK;
711 	else if (uap->how & LOCK_SH)
712 		lf.l_type = F_RDLCK;
713 	else
714 		return (EBADF);
715 	fp->f_flag |= FHASLOCK;
716 	if (uap->how & LOCK_NB)
717 		return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
718 	return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
719 }
720 
721 /*
722  * File Descriptor pseudo-device driver (/dev/fd/).
723  *
724  * Opening minor device N dup()s the file (if any) connected to file
725  * descriptor N belonging to the calling process.  Note that this driver
726  * consists of only the ``open()'' routine, because all subsequent
727  * references to this file will be direct to the other driver.
728  */
729 /* ARGSUSED */
730 fdopen(dev, mode, type, p)
731 	dev_t dev;
732 	int mode, type;
733 	struct proc *p;
734 {
735 
736 	/*
737 	 * XXX Kludge: set curproc->p_dupfd to contain the value of the
738 	 * the file descriptor being sought for duplication. The error
739 	 * return ensures that the vnode for this device will be released
740 	 * by vn_open. Open will detect this special error and take the
741 	 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
742 	 * will simply report the error.
743 	 */
744 	p->p_dupfd = minor(dev);
745 	return (ENODEV);
746 }
747 
748 /*
749  * Duplicate the specified descriptor to a free descriptor.
750  */
751 dupfdopen(fdp, indx, dfd, mode)
752 	register struct filedesc *fdp;
753 	register int indx, dfd;
754 	int mode;
755 {
756 	register struct file *wfp;
757 	struct file *fp;
758 
759 	/*
760 	 * If the to-be-dup'd fd number is greater than the allowed number
761 	 * of file descriptors, or the fd to be dup'd has already been
762 	 * closed, reject.  Note, check for new == old is necessary as
763 	 * falloc could allocate an already closed to-be-dup'd descriptor
764 	 * as the new descriptor.
765 	 */
766 	fp = fdp->fd_ofiles[indx];
767 	if ((u_int)dfd >= fdp->fd_nfiles ||
768 	    (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
769 		return (EBADF);
770 
771 	/*
772 	 * Check that the mode the file is being opened for is a subset
773 	 * of the mode of the existing descriptor.
774 	 */
775 	if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
776 		return (EACCES);
777 	fdp->fd_ofiles[indx] = wfp;
778 	fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
779 	wfp->f_count++;
780 	if (indx > fdp->fd_lastfile)
781 		fdp->fd_lastfile = indx;
782 	return (0);
783 }
784