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