xref: /freebsd/sys/kern/kern_descrip.c (revision 17ee9d00bc1ae1e598c38f25826f861e4bc6c3ce)
1 /*
2  * Copyright (c) 1982, 1986, 1989, 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  * (c) UNIX System Laboratories, Inc.
5  * All or some portions of this file are derived from material licensed
6  * to the University of California by American Telephone and Telegraph
7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8  * the permission of UNIX System Laboratories, Inc.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the University of
21  *	California, Berkeley and its contributors.
22  * 4. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *	@(#)kern_descrip.c	8.6 (Berkeley) 4/19/94
39  * $Id: kern_descrip.c,v 1.7 1994/12/12 12:27:39 bde Exp $
40  */
41 
42 #include <sys/param.h>
43 #include <sys/systm.h>
44 #include <sys/filedesc.h>
45 #include <sys/kernel.h>
46 #include <sys/vnode.h>
47 #include <sys/proc.h>
48 #include <sys/file.h>
49 #include <sys/socket.h>
50 #include <sys/socketvar.h>
51 #include <sys/stat.h>
52 #include <sys/ioctl.h>
53 #include <sys/fcntl.h>
54 #include <sys/malloc.h>
55 #include <sys/syslog.h>
56 #include <sys/unistd.h>
57 #include <sys/resourcevar.h>
58 #include <vm/vm.h>
59 
60 int finishdup(struct filedesc *fdp, int old, int new, int *retval);
61 /*
62  * Descriptor management.
63  */
64 struct file *filehead;	/* head of list of open files */
65 int nfiles;		/* actual number of open files */
66 
67 /*
68  * System calls on descriptors.
69  */
70 struct getdtablesize_args {
71 	int	dummy;
72 };
73 /* ARGSUSED */
74 int
75 getdtablesize(p, uap, retval)
76 	struct proc *p;
77 	struct getdtablesize_args *uap;
78 	int *retval;
79 {
80 
81 	*retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
82 	return (0);
83 }
84 
85 /*
86  * Duplicate a file descriptor to a particular value.
87  */
88 struct dup2_args {
89 	u_int	from;
90 	u_int	to;
91 };
92 /* ARGSUSED */
93 int
94 dup2(p, uap, retval)
95 	struct proc *p;
96 	struct dup2_args *uap;
97 	int *retval;
98 {
99 	register struct filedesc *fdp = p->p_fd;
100 	register u_int old = uap->from, new = uap->to;
101 	int i, error;
102 
103 	if (old >= fdp->fd_nfiles ||
104 	    fdp->fd_ofiles[old] == NULL ||
105 	    new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
106 	    new >= maxfilesperproc)
107 		return (EBADF);
108 	if (old == new) {
109 		*retval = new;
110 		return (0);
111 	}
112 	if (new >= fdp->fd_nfiles) {
113 		if ((error = fdalloc(p, new, &i)))
114 			return (error);
115 		if (new != i)
116 			panic("dup2: fdalloc");
117 	} else if (fdp->fd_ofiles[new]) {
118 		if (fdp->fd_ofileflags[new] & UF_MAPPED)
119 			(void) munmapfd(p, new);
120 		/*
121 		 * dup2() must succeed even if the close has an error.
122 		 */
123 		(void) closef(fdp->fd_ofiles[new], p);
124 	}
125 	return (finishdup(fdp, (int)old, (int)new, retval));
126 }
127 
128 /*
129  * Duplicate a file descriptor.
130  */
131 struct dup_args {
132 	u_int	fd;
133 };
134 /* ARGSUSED */
135 int
136 dup(p, uap, retval)
137 	struct proc *p;
138 	struct dup_args *uap;
139 	int *retval;
140 {
141 	register struct filedesc *fdp;
142 	u_int old;
143 	int new, error;
144 
145 	old = uap->fd;
146 
147 #if 0
148 	/*
149 	 * XXX Compatibility
150 	 */
151 	if (old &~ 077) { uap->fd &= 077; return (dup2(p, uap, retval)); }
152 #endif
153 
154 	fdp = p->p_fd;
155 	if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL)
156 		return (EBADF);
157 	if ((error = fdalloc(p, 0, &new)))
158 		return (error);
159 	return (finishdup(fdp, (int)old, new, retval));
160 }
161 
162 /*
163  * The file control system call.
164  */
165 struct fcntl_args {
166 	int	fd;
167 	int	cmd;
168 	int	arg;
169 };
170 /* ARGSUSED */
171 int
172 fcntl(p, uap, retval)
173 	struct proc *p;
174 	register struct fcntl_args *uap;
175 	int *retval;
176 {
177 	register struct filedesc *fdp = p->p_fd;
178 	register struct file *fp;
179 	register char *pop;
180 	struct vnode *vp;
181 	int i, tmp, error, flg = F_POSIX;
182 	struct flock fl;
183 	u_int newmin;
184 
185 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
186 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
187 		return (EBADF);
188 	pop = &fdp->fd_ofileflags[uap->fd];
189 	switch (uap->cmd) {
190 
191 	case F_DUPFD:
192 		newmin = uap->arg;
193 		if (newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
194 		    newmin >= maxfilesperproc)
195 			return (EINVAL);
196 		if ((error = fdalloc(p, newmin, &i)))
197 			return (error);
198 		return (finishdup(fdp, uap->fd, i, retval));
199 
200 	case F_GETFD:
201 		*retval = *pop & 1;
202 		return (0);
203 
204 	case F_SETFD:
205 		*pop = (*pop &~ 1) | (uap->arg & 1);
206 		return (0);
207 
208 	case F_GETFL:
209 		*retval = OFLAGS(fp->f_flag);
210 		return (0);
211 
212 	case F_SETFL:
213 		fp->f_flag &= ~FCNTLFLAGS;
214 		fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
215 		tmp = fp->f_flag & FNONBLOCK;
216 		error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
217 		if (error)
218 			return (error);
219 		tmp = fp->f_flag & FASYNC;
220 		error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
221 		if (!error)
222 			return (0);
223 		fp->f_flag &= ~FNONBLOCK;
224 		tmp = 0;
225 		(void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
226 		return (error);
227 
228 	case F_GETOWN:
229 		if (fp->f_type == DTYPE_SOCKET) {
230 			*retval = ((struct socket *)fp->f_data)->so_pgid;
231 			return (0);
232 		}
233 		error = (*fp->f_ops->fo_ioctl)
234 			(fp, (int)TIOCGPGRP, (caddr_t)retval, p);
235 		*retval = -*retval;
236 		return (error);
237 
238 	case F_SETOWN:
239 		if (fp->f_type == DTYPE_SOCKET) {
240 			((struct socket *)fp->f_data)->so_pgid = uap->arg;
241 			return (0);
242 		}
243 		if (uap->arg <= 0) {
244 			uap->arg = -uap->arg;
245 		} else {
246 			struct proc *p1 = pfind(uap->arg);
247 			if (p1 == 0)
248 				return (ESRCH);
249 			uap->arg = p1->p_pgrp->pg_id;
250 		}
251 		return ((*fp->f_ops->fo_ioctl)
252 			(fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
253 
254 	case F_SETLKW:
255 		flg |= F_WAIT;
256 		/* Fall into F_SETLK */
257 
258 	case F_SETLK:
259 		if (fp->f_type != DTYPE_VNODE)
260 			return (EBADF);
261 		vp = (struct vnode *)fp->f_data;
262 		/* Copy in the lock structure */
263 		error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
264 		if (error)
265 			return (error);
266 		if (fl.l_whence == SEEK_CUR)
267 			fl.l_start += fp->f_offset;
268 		switch (fl.l_type) {
269 
270 		case F_RDLCK:
271 			if ((fp->f_flag & FREAD) == 0)
272 				return (EBADF);
273 			p->p_flag |= P_ADVLOCK;
274 			return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
275 
276 		case F_WRLCK:
277 			if ((fp->f_flag & FWRITE) == 0)
278 				return (EBADF);
279 			p->p_flag |= P_ADVLOCK;
280 			return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
281 
282 		case F_UNLCK:
283 			return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
284 				F_POSIX));
285 
286 		default:
287 			return (EINVAL);
288 		}
289 
290 	case F_GETLK:
291 		if (fp->f_type != DTYPE_VNODE)
292 			return (EBADF);
293 		vp = (struct vnode *)fp->f_data;
294 		/* Copy in the lock structure */
295 		error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
296 		if (error)
297 			return (error);
298 		if (fl.l_whence == SEEK_CUR)
299 			fl.l_start += fp->f_offset;
300 		if ((error = VOP_ADVLOCK(vp,(caddr_t)p,F_GETLK,&fl,F_POSIX)))
301 			return (error);
302 		return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl)));
303 
304 	default:
305 		return (EINVAL);
306 	}
307 	/* NOTREACHED */
308 }
309 
310 /*
311  * Common code for dup, dup2, and fcntl(F_DUPFD).
312  */
313 int
314 finishdup(fdp, old, new, retval)
315 	register struct filedesc *fdp;
316 	register int old, new, *retval;
317 {
318 	register struct file *fp;
319 
320 	fp = fdp->fd_ofiles[old];
321 	fdp->fd_ofiles[new] = fp;
322 	fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
323 	fp->f_count++;
324 	if (new > fdp->fd_lastfile)
325 		fdp->fd_lastfile = new;
326 	*retval = new;
327 	return (0);
328 }
329 
330 /*
331  * Close a file descriptor.
332  */
333 struct close_args {
334 	int	fd;
335 };
336 /* ARGSUSED */
337 int
338 close(p, uap, retval)
339 	struct proc *p;
340 	struct close_args *uap;
341 	int *retval;
342 {
343 	register struct filedesc *fdp = p->p_fd;
344 	register struct file *fp;
345 	register int fd = uap->fd;
346 	register u_char *pf;
347 
348 	if ((unsigned)fd >= fdp->fd_nfiles ||
349 	    (fp = fdp->fd_ofiles[fd]) == NULL)
350 		return (EBADF);
351 	pf = (u_char *)&fdp->fd_ofileflags[fd];
352 	if (*pf & UF_MAPPED)
353 		(void) munmapfd(p, fd);
354 	fdp->fd_ofiles[fd] = NULL;
355 	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
356 		fdp->fd_lastfile--;
357 	if (fd < fdp->fd_freefile)
358 		fdp->fd_freefile = fd;
359 	*pf = 0;
360 	return (closef(fp, p));
361 }
362 
363 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
364 /*
365  * Return status information about a file descriptor.
366  */
367 struct ofstat_args {
368 	int	fd;
369 	struct	ostat *sb;
370 };
371 /* ARGSUSED */
372 int
373 ofstat(p, uap, retval)
374 	struct proc *p;
375 	register struct ofstat_args *uap;
376 	int *retval;
377 {
378 	register struct filedesc *fdp = p->p_fd;
379 	register struct file *fp;
380 	struct stat ub;
381 	struct ostat oub;
382 	int error;
383 
384 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
385 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
386 		return (EBADF);
387 	switch (fp->f_type) {
388 
389 	case DTYPE_VNODE:
390 		error = vn_stat((struct vnode *)fp->f_data, &ub, p);
391 		break;
392 
393 	case DTYPE_SOCKET:
394 		error = soo_stat((struct socket *)fp->f_data, &ub);
395 		break;
396 
397 	default:
398 		panic("ofstat");
399 		/*NOTREACHED*/
400 	}
401 	cvtstat(&ub, &oub);
402 	if (error == 0)
403 		error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub));
404 	return (error);
405 }
406 #endif /* COMPAT_43 || COMPAT_SUNOS */
407 
408 /*
409  * Return status information about a file descriptor.
410  */
411 struct fstat_args {
412 	int	fd;
413 	struct	stat *sb;
414 };
415 /* ARGSUSED */
416 int
417 fstat(p, uap, retval)
418 	struct proc *p;
419 	register struct fstat_args *uap;
420 	int *retval;
421 {
422 	register struct filedesc *fdp = p->p_fd;
423 	register struct file *fp;
424 	struct stat ub;
425 	int error;
426 
427 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
428 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
429 		return (EBADF);
430 	switch (fp->f_type) {
431 
432 	case DTYPE_VNODE:
433 		error = vn_stat((struct vnode *)fp->f_data, &ub, p);
434 		break;
435 
436 	case DTYPE_SOCKET:
437 		error = soo_stat((struct socket *)fp->f_data, &ub);
438 		break;
439 
440 	default:
441 		panic("fstat");
442 		/*NOTREACHED*/
443 	}
444 	if (error == 0)
445 		error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
446 	return (error);
447 }
448 
449 /*
450  * Return pathconf information about a file descriptor.
451  */
452 struct fpathconf_args {
453 	int	fd;
454 	int	name;
455 };
456 /* ARGSUSED */
457 int
458 fpathconf(p, uap, retval)
459 	struct proc *p;
460 	register struct fpathconf_args *uap;
461 	int *retval;
462 {
463 	struct filedesc *fdp = p->p_fd;
464 	struct file *fp;
465 	struct vnode *vp;
466 
467 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
468 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
469 		return (EBADF);
470 	switch (fp->f_type) {
471 
472 	case DTYPE_SOCKET:
473 		if (uap->name != _PC_PIPE_BUF)
474 			return (EINVAL);
475 		*retval = PIPE_BUF;
476 		return (0);
477 
478 	case DTYPE_VNODE:
479 		vp = (struct vnode *)fp->f_data;
480 		return (VOP_PATHCONF(vp, uap->name, retval));
481 
482 	default:
483 		panic("fpathconf");
484 	}
485 	/*NOTREACHED*/
486 }
487 
488 /*
489  * Allocate a file descriptor for the process.
490  */
491 int fdexpand;
492 
493 int
494 fdalloc(p, want, result)
495 	struct proc *p;
496 	int want;
497 	int *result;
498 {
499 	register struct filedesc *fdp = p->p_fd;
500 	register int i;
501 	int lim, last, nfiles;
502 	struct file **newofile;
503 	char *newofileflags;
504 
505 	/*
506 	 * Search for a free descriptor starting at the higher
507 	 * of want or fd_freefile.  If that fails, consider
508 	 * expanding the ofile array.
509 	 */
510 	lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
511 	for (;;) {
512 		last = min(fdp->fd_nfiles, lim);
513 		if ((i = want) < fdp->fd_freefile)
514 			i = fdp->fd_freefile;
515 		for (; i < last; i++) {
516 			if (fdp->fd_ofiles[i] == NULL) {
517 				fdp->fd_ofileflags[i] = 0;
518 				if (i > fdp->fd_lastfile)
519 					fdp->fd_lastfile = i;
520 				if (want <= fdp->fd_freefile)
521 					fdp->fd_freefile = i;
522 				*result = i;
523 				return (0);
524 			}
525 		}
526 
527 		/*
528 		 * No space in current array.  Expand?
529 		 */
530 		if (fdp->fd_nfiles >= lim)
531 			return (EMFILE);
532 		if (fdp->fd_nfiles < NDEXTENT)
533 			nfiles = NDEXTENT;
534 		else
535 			nfiles = 2 * fdp->fd_nfiles;
536 		MALLOC(newofile, struct file **, nfiles * OFILESIZE,
537 		    M_FILEDESC, M_WAITOK);
538 		newofileflags = (char *) &newofile[nfiles];
539 		/*
540 		 * Copy the existing ofile and ofileflags arrays
541 		 * and zero the new portion of each array.
542 		 */
543 		bcopy(fdp->fd_ofiles, newofile,
544 			(i = sizeof(struct file *) * fdp->fd_nfiles));
545 		bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
546 		bcopy(fdp->fd_ofileflags, newofileflags,
547 			(i = sizeof(char) * fdp->fd_nfiles));
548 		bzero(newofileflags + i, nfiles * sizeof(char) - i);
549 		if (fdp->fd_nfiles > NDFILE)
550 			FREE(fdp->fd_ofiles, M_FILEDESC);
551 		fdp->fd_ofiles = newofile;
552 		fdp->fd_ofileflags = newofileflags;
553 		fdp->fd_nfiles = nfiles;
554 		fdexpand++;
555 	}
556 	return (0);
557 }
558 
559 /*
560  * Check to see whether n user file descriptors
561  * are available to the process p.
562  */
563 int
564 fdavail(p, n)
565 	struct proc *p;
566 	register int n;
567 {
568 	register struct filedesc *fdp = p->p_fd;
569 	register struct file **fpp;
570 	register int i, lim;
571 
572 	lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
573 	if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
574 		return (1);
575 	fpp = &fdp->fd_ofiles[fdp->fd_freefile];
576 	for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)
577 		if (*fpp == NULL && --n <= 0)
578 			return (1);
579 	return (0);
580 }
581 
582 /*
583  * Create a new open file structure and allocate
584  * a file decriptor for the process that refers to it.
585  */
586 int
587 falloc(p, resultfp, resultfd)
588 	register struct proc *p;
589 	struct file **resultfp;
590 	int *resultfd;
591 {
592 	register struct file *fp, *fq, **fpp;
593 	int error, i;
594 
595 	if ((error = fdalloc(p, 0, &i)))
596 		return (error);
597 	if (nfiles >= maxfiles) {
598 		tablefull("file");
599 		return (ENFILE);
600 	}
601 	/*
602 	 * Allocate a new file descriptor.
603 	 * If the process has file descriptor zero open, add to the list
604 	 * of open files at that point, otherwise put it at the front of
605 	 * the list of open files.
606 	 */
607 	nfiles++;
608 	MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
609 	bzero(fp, sizeof(struct file));
610 	if ((fq = p->p_fd->fd_ofiles[0]))
611 		fpp = &fq->f_filef;
612 	else
613 		fpp = &filehead;
614 	p->p_fd->fd_ofiles[i] = fp;
615 	if ((fq = *fpp))
616 		fq->f_fileb = &fp->f_filef;
617 	fp->f_filef = fq;
618 	fp->f_fileb = fpp;
619 	*fpp = fp;
620 	fp->f_count = 1;
621 	fp->f_cred = p->p_ucred;
622 	crhold(fp->f_cred);
623 	if (resultfp)
624 		*resultfp = fp;
625 	if (resultfd)
626 		*resultfd = i;
627 	return (0);
628 }
629 
630 /*
631  * Free a file descriptor.
632  */
633 void
634 ffree(fp)
635 	register struct file *fp;
636 {
637 	register struct file *fq;
638 
639 	if ((fq = fp->f_filef))
640 		fq->f_fileb = fp->f_fileb;
641 	*fp->f_fileb = fq;
642 	crfree(fp->f_cred);
643 #ifdef DIAGNOSTIC
644 	fp->f_filef = NULL;
645 	fp->f_fileb = NULL;
646 	fp->f_count = 0;
647 #endif
648 	nfiles--;
649 	FREE(fp, M_FILE);
650 }
651 
652 /*
653  * Copy a filedesc structure.
654  */
655 struct filedesc *
656 fdcopy(p)
657 	struct proc *p;
658 {
659 	register struct filedesc *newfdp, *fdp = p->p_fd;
660 	register struct file **fpp;
661 	register int i;
662 
663 	MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
664 	    M_FILEDESC, M_WAITOK);
665 	bcopy(fdp, newfdp, sizeof(struct filedesc));
666 	VREF(newfdp->fd_cdir);
667 	if (newfdp->fd_rdir)
668 		VREF(newfdp->fd_rdir);
669 	newfdp->fd_refcnt = 1;
670 
671 	/*
672 	 * If the number of open files fits in the internal arrays
673 	 * of the open file structure, use them, otherwise allocate
674 	 * additional memory for the number of descriptors currently
675 	 * in use.
676 	 */
677 	if (newfdp->fd_lastfile < NDFILE) {
678 		newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
679 		newfdp->fd_ofileflags =
680 		    ((struct filedesc0 *) newfdp)->fd_dfileflags;
681 		i = NDFILE;
682 	} else {
683 		/*
684 		 * Compute the smallest multiple of NDEXTENT needed
685 		 * for the file descriptors currently in use,
686 		 * allowing the table to shrink.
687 		 */
688 		i = newfdp->fd_nfiles;
689 		while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
690 			i /= 2;
691 		MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
692 		    M_FILEDESC, M_WAITOK);
693 		newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
694 	}
695 	newfdp->fd_nfiles = i;
696 	bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
697 	bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
698 	fpp = newfdp->fd_ofiles;
699 	for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
700 		if (*fpp != NULL)
701 			(*fpp)->f_count++;
702 	return (newfdp);
703 }
704 
705 /*
706  * Release a filedesc structure.
707  */
708 void
709 fdfree(p)
710 	struct proc *p;
711 {
712 	register struct filedesc *fdp = p->p_fd;
713 	struct file **fpp;
714 	register int i;
715 
716 	if (--fdp->fd_refcnt > 0)
717 		return;
718 	fpp = fdp->fd_ofiles;
719 	for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
720 		if (*fpp)
721 			(void) closef(*fpp, p);
722 	if (fdp->fd_nfiles > NDFILE)
723 		FREE(fdp->fd_ofiles, M_FILEDESC);
724 	vrele(fdp->fd_cdir);
725 	if (fdp->fd_rdir)
726 		vrele(fdp->fd_rdir);
727 	FREE(fdp, M_FILEDESC);
728 }
729 
730 /*
731  * Close any files on exec?
732  */
733 void
734 fdcloseexec(p)
735 	struct proc *p;
736 {
737 	struct filedesc *fdp = p->p_fd;
738 	struct file **fpp;
739 	char *fdfp;
740 	register int i;
741 
742 	fpp = fdp->fd_ofiles;
743 	fdfp = fdp->fd_ofileflags;
744 	for (i = 0; i <= fdp->fd_lastfile; i++, fpp++, fdfp++)
745 		if (*fpp != NULL && (*fdfp & UF_EXCLOSE)) {
746 			if (*fdfp & UF_MAPPED)
747 				(void) munmapfd(p, i);
748 			(void) closef(*fpp, p);
749 			*fpp = NULL;
750 			*fdfp = 0;
751 			if (i < fdp->fd_freefile)
752 				fdp->fd_freefile = i;
753 		}
754 	while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
755 		fdp->fd_lastfile--;
756 }
757 
758 /*
759  * Internal form of close.
760  * Decrement reference count on file structure.
761  * Note: p may be NULL when closing a file
762  * that was being passed in a message.
763  */
764 int
765 closef(fp, p)
766 	register struct file *fp;
767 	register struct proc *p;
768 {
769 	struct vnode *vp;
770 	struct flock lf;
771 	int error;
772 
773 	if (fp == NULL)
774 		return (0);
775 	/*
776 	 * POSIX record locking dictates that any close releases ALL
777 	 * locks owned by this process.  This is handled by setting
778 	 * a flag in the unlock to free ONLY locks obeying POSIX
779 	 * semantics, and not to free BSD-style file locks.
780 	 * If the descriptor was in a message, POSIX-style locks
781 	 * aren't passed with the descriptor.
782 	 */
783 	if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
784 		lf.l_whence = SEEK_SET;
785 		lf.l_start = 0;
786 		lf.l_len = 0;
787 		lf.l_type = F_UNLCK;
788 		vp = (struct vnode *)fp->f_data;
789 		(void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
790 	}
791 	if (--fp->f_count > 0)
792 		return (0);
793 	if (fp->f_count < 0)
794 		panic("closef: count < 0");
795 	if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
796 		lf.l_whence = SEEK_SET;
797 		lf.l_start = 0;
798 		lf.l_len = 0;
799 		lf.l_type = F_UNLCK;
800 		vp = (struct vnode *)fp->f_data;
801 		(void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
802 	}
803 	if (fp->f_ops)
804 		error = (*fp->f_ops->fo_close)(fp, p);
805 	else
806 		error = 0;
807 	ffree(fp);
808 	return (error);
809 }
810 
811 /*
812  * Apply an advisory lock on a file descriptor.
813  *
814  * Just attempt to get a record lock of the requested type on
815  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
816  */
817 struct flock_args {
818 	int	fd;
819 	int	how;
820 };
821 /* ARGSUSED */
822 int
823 flock(p, uap, retval)
824 	struct proc *p;
825 	register struct flock_args *uap;
826 	int *retval;
827 {
828 	register struct filedesc *fdp = p->p_fd;
829 	register struct file *fp;
830 	struct vnode *vp;
831 	struct flock lf;
832 
833 	if ((unsigned)uap->fd >= fdp->fd_nfiles ||
834 	    (fp = fdp->fd_ofiles[uap->fd]) == NULL)
835 		return (EBADF);
836 	if (fp->f_type != DTYPE_VNODE)
837 		return (EOPNOTSUPP);
838 	vp = (struct vnode *)fp->f_data;
839 	lf.l_whence = SEEK_SET;
840 	lf.l_start = 0;
841 	lf.l_len = 0;
842 	if (uap->how & LOCK_UN) {
843 		lf.l_type = F_UNLCK;
844 		fp->f_flag &= ~FHASLOCK;
845 		return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
846 	}
847 	if (uap->how & LOCK_EX)
848 		lf.l_type = F_WRLCK;
849 	else if (uap->how & LOCK_SH)
850 		lf.l_type = F_RDLCK;
851 	else
852 		return (EBADF);
853 	fp->f_flag |= FHASLOCK;
854 	if (uap->how & LOCK_NB)
855 		return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
856 	return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
857 }
858 
859 /*
860  * File Descriptor pseudo-device driver (/dev/fd/).
861  *
862  * Opening minor device N dup()s the file (if any) connected to file
863  * descriptor N belonging to the calling process.  Note that this driver
864  * consists of only the ``open()'' routine, because all subsequent
865  * references to this file will be direct to the other driver.
866  */
867 /* ARGSUSED */
868 int
869 fdopen(dev, mode, type, p)
870 	dev_t dev;
871 	int mode, type;
872 	struct proc *p;
873 {
874 
875 	/*
876 	 * XXX Kludge: set curproc->p_dupfd to contain the value of the
877 	 * the file descriptor being sought for duplication. The error
878 	 * return ensures that the vnode for this device will be released
879 	 * by vn_open. Open will detect this special error and take the
880 	 * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
881 	 * will simply report the error.
882 	 */
883 	p->p_dupfd = minor(dev);
884 	return (ENODEV);
885 }
886 
887 /*
888  * Duplicate the specified descriptor to a free descriptor.
889  */
890 int
891 dupfdopen(fdp, indx, dfd, mode, error)
892 	register struct filedesc *fdp;
893 	register int indx, dfd;
894 	int mode;
895 	int error;
896 {
897 	register struct file *wfp;
898 	struct file *fp;
899 
900 	/*
901 	 * If the to-be-dup'd fd number is greater than the allowed number
902 	 * of file descriptors, or the fd to be dup'd has already been
903 	 * closed, reject.  Note, check for new == old is necessary as
904 	 * falloc could allocate an already closed to-be-dup'd descriptor
905 	 * as the new descriptor.
906 	 */
907 	fp = fdp->fd_ofiles[indx];
908 	if ((u_int)dfd >= fdp->fd_nfiles ||
909 	    (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
910 		return (EBADF);
911 
912 	/*
913 	 * There are two cases of interest here.
914 	 *
915 	 * For ENODEV simply dup (dfd) to file descriptor
916 	 * (indx) and return.
917 	 *
918 	 * For ENXIO steal away the file structure from (dfd) and
919 	 * store it in (indx).  (dfd) is effectively closed by
920 	 * this operation.
921 	 *
922 	 * Any other error code is just returned.
923 	 */
924 	switch (error) {
925 	case ENODEV:
926 		/*
927 		 * Check that the mode the file is being opened for is a
928 		 * subset of the mode of the existing descriptor.
929 		 */
930 		if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
931 			return (EACCES);
932 		fdp->fd_ofiles[indx] = wfp;
933 		fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
934 		wfp->f_count++;
935 		if (indx > fdp->fd_lastfile)
936 			fdp->fd_lastfile = indx;
937 		return (0);
938 
939 	case ENXIO:
940 		/*
941 		 * Steal away the file pointer from dfd, and stuff it into indx.
942 		 */
943 		fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
944 		fdp->fd_ofiles[dfd] = NULL;
945 		fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
946 		fdp->fd_ofileflags[dfd] = 0;
947 		/*
948 		 * Complete the clean up of the filedesc structure by
949 		 * recomputing the various hints.
950 		 */
951 		if (indx > fdp->fd_lastfile)
952 			fdp->fd_lastfile = indx;
953 		else
954 			while (fdp->fd_lastfile > 0 &&
955 			       fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
956 				fdp->fd_lastfile--;
957 			if (dfd < fdp->fd_freefile)
958 				fdp->fd_freefile = dfd;
959 		return (0);
960 
961 	default:
962 		return (error);
963 	}
964 	/* NOTREACHED */
965 }
966