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