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