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