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