Augment falloc() to support thread-only file pointers (with no integer file
[dragonfly.git] / sys / kern / kern_descrip.c
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  * $FreeBSD: src/sys/kern/kern_descrip.c,v 1.81.2.17 2003/06/06 20:21:32 tegge Exp $
40  * $DragonFly: src/sys/kern/kern_descrip.c,v 1.14 2003/10/13 18:01:25 dillon Exp $
41  */
42
43 #include "opt_compat.h"
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/malloc.h>
47 #include <sys/sysproto.h>
48 #include <sys/conf.h>
49 #include <sys/filedesc.h>
50 #include <sys/kernel.h>
51 #include <sys/sysctl.h>
52 #include <sys/vnode.h>
53 #include <sys/proc.h>
54 #include <sys/namei.h>
55 #include <sys/file.h>
56 #include <sys/stat.h>
57 #include <sys/filio.h>
58 #include <sys/fcntl.h>
59 #include <sys/unistd.h>
60 #include <sys/resourcevar.h>
61 #include <sys/event.h>
62
63 #include <vm/vm.h>
64 #include <vm/vm_extern.h>
65
66 #include <sys/file2.h>
67
68 static MALLOC_DEFINE(M_FILEDESC, "file desc", "Open file descriptor table");
69 static MALLOC_DEFINE(M_FILEDESC_TO_LEADER, "file desc to leader",
70                      "file desc to leader structures");
71 MALLOC_DEFINE(M_FILE, "file", "Open file structure");
72 static MALLOC_DEFINE(M_SIGIO, "sigio", "sigio structures");
73
74 static   d_open_t  fdopen;
75 #define NUMFDESC 64
76
77 #define CDEV_MAJOR 22
78 static struct cdevsw fildesc_cdevsw = {
79         /* name */      "FD",
80         /* maj */       CDEV_MAJOR,
81         /* flags */     0,
82         /* port */      NULL,
83         /* autoq */     0,
84
85         /* open */      fdopen,
86         /* close */     noclose,
87         /* read */      noread,
88         /* write */     nowrite,
89         /* ioctl */     noioctl,
90         /* poll */      nopoll,
91         /* mmap */      nommap,
92         /* strategy */  nostrategy,
93         /* dump */      nodump,
94         /* psize */     nopsize
95 };
96
97 static int do_dup (struct filedesc *fdp, int old, int new, register_t *retval, struct proc *p);
98 static int badfo_readwrite (struct file *fp, struct uio *uio,
99     struct ucred *cred, int flags, struct thread *td);
100 static int badfo_ioctl (struct file *fp, u_long com, caddr_t data,
101     struct thread *td);
102 static int badfo_poll (struct file *fp, int events,
103     struct ucred *cred, struct thread *td);
104 static int badfo_kqfilter (struct file *fp, struct knote *kn);
105 static int badfo_stat (struct file *fp, struct stat *sb, struct thread *td);
106 static int badfo_close (struct file *fp, struct thread *td);
107
108 /*
109  * Descriptor management.
110  */
111 struct filelist filehead;       /* head of list of open files */
112 int nfiles;                     /* actual number of open files */
113 extern int cmask;       
114
115 /*
116  * System calls on descriptors.
117  */
118 /* ARGSUSED */
119 int
120 getdtablesize(struct getdtablesize_args *uap) 
121 {
122         struct proc *p = curproc;
123
124         uap->sysmsg_result = 
125             min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
126         return (0);
127 }
128
129 /*
130  * Duplicate a file descriptor to a particular value.
131  *
132  * note: keep in mind that a potential race condition exists when closing
133  * descriptors from a shared descriptor table (via rfork).
134  */
135 /* ARGSUSED */
136 int
137 dup2(struct dup2_args *uap)
138 {
139         struct proc *p = curproc;
140         struct filedesc *fdp = p->p_fd;
141         u_int old = uap->from, new = uap->to;
142         int i, error;
143
144 retry:
145         if (old >= fdp->fd_nfiles ||
146             fdp->fd_ofiles[old] == NULL ||
147             new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
148             new >= maxfilesperproc) {
149                 return (EBADF);
150         }
151         if (old == new) {
152                 uap->sysmsg_result = new;
153                 return (0);
154         }
155         if (new >= fdp->fd_nfiles) {
156                 if ((error = fdalloc(p, new, &i)))
157                         return (error);
158                 /*
159                  * fdalloc() may block, retest everything.
160                  */
161                 goto retry;
162         }
163         return (do_dup(fdp, (int)old, (int)new, uap->sysmsg_fds, p));
164 }
165
166 /*
167  * Duplicate a file descriptor.
168  */
169 /* ARGSUSED */
170 int
171 dup(struct dup_args *uap)
172 {
173         struct proc *p = curproc;
174         struct filedesc *fdp;
175         u_int old;
176         int new, error;
177
178         old = uap->fd;
179         fdp = p->p_fd;
180         if (old >= fdp->fd_nfiles || fdp->fd_ofiles[old] == NULL)
181                 return (EBADF);
182         if ((error = fdalloc(p, 0, &new)))
183                 return (error);
184         return (do_dup(fdp, (int)old, new, uap->sysmsg_fds, p));
185 }
186
187 /*
188  * The file control system call.
189  */
190 /* ARGSUSED */
191 int
192 fcntl(struct fcntl_args *uap)
193 {
194         struct thread *td = curthread;
195         struct proc *p = td->td_proc;
196         struct filedesc *fdp = p->p_fd;
197         struct file *fp;
198         char *pop;
199         struct vnode *vp;
200         int i, tmp, error, flg = F_POSIX;
201         struct flock fl;
202         u_int newmin;
203
204         KKASSERT(p);
205
206         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
207             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
208                 return (EBADF);
209         pop = &fdp->fd_ofileflags[uap->fd];
210
211         switch (uap->cmd) {
212         case F_DUPFD:
213                 newmin = uap->arg;
214                 if (newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
215                     newmin >= maxfilesperproc)
216                         return (EINVAL);
217                 if ((error = fdalloc(p, newmin, &i)))
218                         return (error);
219                 return (do_dup(fdp, uap->fd, i, uap->sysmsg_fds, p));
220
221         case F_GETFD:
222                 uap->sysmsg_result = (*pop & UF_EXCLOSE) ? FD_CLOEXEC : 0;
223                 return (0);
224
225         case F_SETFD:
226                 *pop = (*pop &~ UF_EXCLOSE) |
227                     (uap->arg & FD_CLOEXEC ? UF_EXCLOSE : 0);
228                 return (0);
229
230         case F_GETFL:
231                 uap->sysmsg_result = OFLAGS(fp->f_flag);
232                 return (0);
233
234         case F_SETFL:
235                 fhold(fp);
236                 fp->f_flag &= ~FCNTLFLAGS;
237                 fp->f_flag |= FFLAGS(uap->arg & ~O_ACCMODE) & FCNTLFLAGS;
238                 tmp = fp->f_flag & FNONBLOCK;
239                 error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, td);
240                 if (error) {
241                         fdrop(fp, td);
242                         return (error);
243                 }
244                 tmp = fp->f_flag & FASYNC;
245                 error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, td);
246                 if (!error) {
247                         fdrop(fp, td);
248                         return (0);
249                 }
250                 fp->f_flag &= ~FNONBLOCK;
251                 tmp = 0;
252                 (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, td);
253                 fdrop(fp, td);
254                 return (error);
255
256         case F_GETOWN:
257                 fhold(fp);
258                 error = fo_ioctl(fp, FIOGETOWN, (caddr_t)uap->sysmsg_fds, td);
259                 fdrop(fp, td);
260                 return(error);
261
262         case F_SETOWN:
263                 fhold(fp);
264                 error = fo_ioctl(fp, FIOSETOWN, (caddr_t)&uap->arg, td);
265                 fdrop(fp, td);
266                 return(error);
267
268         case F_SETLKW:
269                 flg |= F_WAIT;
270                 /* Fall into F_SETLK */
271
272         case F_SETLK:
273                 if (fp->f_type != DTYPE_VNODE)
274                         return (EBADF);
275                 vp = (struct vnode *)fp->f_data;
276
277                 /*
278                  * copyin/lockop may block
279                  */
280                 fhold(fp);
281                 /* Copy in the lock structure */
282                 error = copyin((caddr_t)(intptr_t)uap->arg, (caddr_t)&fl,
283                     sizeof(fl));
284                 if (error) {
285                         fdrop(fp, td);
286                         return (error);
287                 }
288                 if (fl.l_whence == SEEK_CUR)
289                         fl.l_start += fp->f_offset;
290
291                 switch (fl.l_type) {
292                 case F_RDLCK:
293                         if ((fp->f_flag & FREAD) == 0) {
294                                 error = EBADF;
295                                 break;
296                         }
297                         p->p_leader->p_flag |= P_ADVLOCK;
298                         error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_SETLK,
299                             &fl, flg);
300                         break;
301                 case F_WRLCK:
302                         if ((fp->f_flag & FWRITE) == 0) {
303                                 error = EBADF;
304                                 break;
305                         }
306                         p->p_leader->p_flag |= P_ADVLOCK;
307                         error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_SETLK,
308                             &fl, flg);
309                         break;
310                 case F_UNLCK:
311                         error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_UNLCK,
312                                 &fl, F_POSIX);
313                         break;
314                 default:
315                         error = EINVAL;
316                         break;
317                 }
318                 /* Check for race with close */
319                 if ((unsigned) uap->fd >= fdp->fd_nfiles ||
320                     fp != fdp->fd_ofiles[uap->fd]) {
321                         fl.l_whence = SEEK_SET;
322                         fl.l_start = 0;
323                         fl.l_len = 0;
324                         fl.l_type = F_UNLCK;
325                         (void) VOP_ADVLOCK(vp, (caddr_t)p->p_leader,
326                                            F_UNLCK, &fl, F_POSIX);
327                 }
328                 fdrop(fp, td);
329                 return(error);
330
331         case F_GETLK:
332                 if (fp->f_type != DTYPE_VNODE)
333                         return (EBADF);
334                 vp = (struct vnode *)fp->f_data;
335                 /*
336                  * copyin/lockop may block
337                  */
338                 fhold(fp);
339                 /* Copy in the lock structure */
340                 error = copyin((caddr_t)(intptr_t)uap->arg, (caddr_t)&fl,
341                     sizeof(fl));
342                 if (error) {
343                         fdrop(fp, td);
344                         return (error);
345                 }
346                 if (fl.l_type != F_RDLCK && fl.l_type != F_WRLCK &&
347                     fl.l_type != F_UNLCK) {
348                         fdrop(fp, td);
349                         return (EINVAL);
350                 }
351                 if (fl.l_whence == SEEK_CUR)
352                         fl.l_start += fp->f_offset;
353                 error = VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_GETLK,
354                             &fl, F_POSIX);
355                 fdrop(fp, td);
356                 if (error == 0) {
357                         error = copyout((caddr_t)&fl,
358                                     (caddr_t)(intptr_t)uap->arg, sizeof(fl));
359                 }
360                 return(error);
361         default:
362                 return (EINVAL);
363         }
364         /* NOTREACHED */
365 }
366
367 /*
368  * Common code for dup, dup2, and fcntl(F_DUPFD).
369  */
370 static int
371 do_dup(fdp, old, new, retval, p)
372         struct filedesc *fdp;
373         int old, new;
374         register_t *retval;
375         struct proc *p;
376 {
377         struct thread *td = p->p_thread;
378         struct file *fp;
379         struct file *delfp;
380         int holdleaders;
381
382         /*
383          * Save info on the descriptor being overwritten.  We have
384          * to do the unmap now, but we cannot close it without
385          * introducing an ownership race for the slot.
386          */
387         delfp = fdp->fd_ofiles[new];
388         if (delfp != NULL && p->p_fdtol != NULL) {
389                 /*
390                  * Ask fdfree() to sleep to ensure that all relevant
391                  * process leaders can be traversed in closef().
392                  */
393                 fdp->fd_holdleaderscount++;
394                 holdleaders = 1;
395         } else
396                 holdleaders = 0;
397 #if 0
398         if (delfp && (fdp->fd_ofileflags[new] & UF_MAPPED))
399                 (void) munmapfd(p, new);
400 #endif
401
402         /*
403          * Duplicate the source descriptor, update lastfile
404          */
405         fp = fdp->fd_ofiles[old];
406         fdp->fd_ofiles[new] = fp;
407         fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
408         fhold(fp);
409         if (new > fdp->fd_lastfile)
410                 fdp->fd_lastfile = new;
411         *retval = new;
412
413         /*
414          * If we dup'd over a valid file, we now own the reference to it
415          * and must dispose of it using closef() semantics (as if a
416          * close() were performed on it).
417          */
418         if (delfp) {
419                 (void) closef(delfp, td);
420                 if (holdleaders) {
421                         fdp->fd_holdleaderscount--;
422                         if (fdp->fd_holdleaderscount == 0 &&
423                             fdp->fd_holdleaderswakeup != 0) {
424                                 fdp->fd_holdleaderswakeup = 0;
425                                 wakeup(&fdp->fd_holdleaderscount);
426                         }
427                 }
428         }
429         return (0);
430 }
431
432 /*
433  * If sigio is on the list associated with a process or process group,
434  * disable signalling from the device, remove sigio from the list and
435  * free sigio.
436  */
437 void
438 funsetown(sigio)
439         struct sigio *sigio;
440 {
441         int s;
442
443         if (sigio == NULL)
444                 return;
445         s = splhigh();
446         *(sigio->sio_myref) = NULL;
447         splx(s);
448         if (sigio->sio_pgid < 0) {
449                 SLIST_REMOVE(&sigio->sio_pgrp->pg_sigiolst, sigio,
450                              sigio, sio_pgsigio);
451         } else /* if ((*sigiop)->sio_pgid > 0) */ {
452                 SLIST_REMOVE(&sigio->sio_proc->p_sigiolst, sigio,
453                              sigio, sio_pgsigio);
454         }
455         crfree(sigio->sio_ucred);
456         FREE(sigio, M_SIGIO);
457 }
458
459 /* Free a list of sigio structures. */
460 void
461 funsetownlst(sigiolst)
462         struct sigiolst *sigiolst;
463 {
464         struct sigio *sigio;
465
466         while ((sigio = SLIST_FIRST(sigiolst)) != NULL)
467                 funsetown(sigio);
468 }
469
470 /*
471  * This is common code for FIOSETOWN ioctl called by fcntl(fd, F_SETOWN, arg).
472  *
473  * After permission checking, add a sigio structure to the sigio list for
474  * the process or process group.
475  */
476 int
477 fsetown(pgid, sigiop)
478         pid_t pgid;
479         struct sigio **sigiop;
480 {
481         struct proc *proc;
482         struct pgrp *pgrp;
483         struct sigio *sigio;
484         int s;
485
486         if (pgid == 0) {
487                 funsetown(*sigiop);
488                 return (0);
489         }
490         if (pgid > 0) {
491                 proc = pfind(pgid);
492                 if (proc == NULL)
493                         return (ESRCH);
494
495                 /*
496                  * Policy - Don't allow a process to FSETOWN a process
497                  * in another session.
498                  *
499                  * Remove this test to allow maximum flexibility or
500                  * restrict FSETOWN to the current process or process
501                  * group for maximum safety.
502                  */
503                 if (proc->p_session != curproc->p_session)
504                         return (EPERM);
505
506                 pgrp = NULL;
507         } else /* if (pgid < 0) */ {
508                 pgrp = pgfind(-pgid);
509                 if (pgrp == NULL)
510                         return (ESRCH);
511
512                 /*
513                  * Policy - Don't allow a process to FSETOWN a process
514                  * in another session.
515                  *
516                  * Remove this test to allow maximum flexibility or
517                  * restrict FSETOWN to the current process or process
518                  * group for maximum safety.
519                  */
520                 if (pgrp->pg_session != curproc->p_session)
521                         return (EPERM);
522
523                 proc = NULL;
524         }
525         funsetown(*sigiop);
526         MALLOC(sigio, struct sigio *, sizeof(struct sigio), M_SIGIO, M_WAITOK);
527         if (pgid > 0) {
528                 SLIST_INSERT_HEAD(&proc->p_sigiolst, sigio, sio_pgsigio);
529                 sigio->sio_proc = proc;
530         } else {
531                 SLIST_INSERT_HEAD(&pgrp->pg_sigiolst, sigio, sio_pgsigio);
532                 sigio->sio_pgrp = pgrp;
533         }
534         sigio->sio_pgid = pgid;
535         sigio->sio_ucred = crhold(curproc->p_ucred);
536         /* It would be convenient if p_ruid was in ucred. */
537         sigio->sio_ruid = curproc->p_ucred->cr_ruid;
538         sigio->sio_myref = sigiop;
539         s = splhigh();
540         *sigiop = sigio;
541         splx(s);
542         return (0);
543 }
544
545 /*
546  * This is common code for FIOGETOWN ioctl called by fcntl(fd, F_GETOWN, arg).
547  */
548 pid_t
549 fgetown(sigio)
550         struct sigio *sigio;
551 {
552         return (sigio != NULL ? sigio->sio_pgid : 0);
553 }
554
555 /*
556  * Close a file descriptor.
557  */
558 /* ARGSUSED */
559 int
560 close(struct close_args *uap)
561 {
562         struct thread *td = curthread;
563         struct proc *p = td->td_proc;
564         struct filedesc *fdp;
565         struct file *fp;
566         int fd = uap->fd;
567         int error;
568         int holdleaders;
569
570         KKASSERT(p);
571         fdp = p->p_fd;
572
573         if ((unsigned)fd >= fdp->fd_nfiles ||
574             (fp = fdp->fd_ofiles[fd]) == NULL)
575                 return (EBADF);
576 #if 0
577         if (fdp->fd_ofileflags[fd] & UF_MAPPED)
578                 (void) munmapfd(p, fd);
579 #endif
580         fdp->fd_ofiles[fd] = NULL;
581         fdp->fd_ofileflags[fd] = 0;
582         holdleaders = 0;
583         if (p->p_fdtol != NULL) {
584                 /*
585                  * Ask fdfree() to sleep to ensure that all relevant
586                  * process leaders can be traversed in closef().
587                  */
588                 fdp->fd_holdleaderscount++;
589                 holdleaders = 1;
590         }
591
592         /*
593          * we now hold the fp reference that used to be owned by the descriptor
594          * array.
595          */
596         while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
597                 fdp->fd_lastfile--;
598         if (fd < fdp->fd_freefile)
599                 fdp->fd_freefile = fd;
600         if (fd < fdp->fd_knlistsize)
601                 knote_fdclose(p, fd);
602         error = closef(fp, td);
603         if (holdleaders) {
604                 fdp->fd_holdleaderscount--;
605                 if (fdp->fd_holdleaderscount == 0 &&
606                     fdp->fd_holdleaderswakeup != 0) {
607                         fdp->fd_holdleaderswakeup = 0;
608                         wakeup(&fdp->fd_holdleaderscount);
609                 }
610         }
611         return (error);
612 }
613
614 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
615 /*
616  * Return status information about a file descriptor.
617  */
618 /* ARGSUSED */
619 int
620 ofstat(struct ofstat_args *uap)
621 {
622         struct thread *td = curthread;
623         struct proc *p = td->td_proc;
624         struct filedesc *fdp;
625         struct file *fp;
626         struct stat ub;
627         struct ostat oub;
628         int error;
629
630         KKASSERT(p);
631         fdp = p->p_fd;
632         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
633             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
634                 return (EBADF);
635         fhold(fp);
636         error = fo_stat(fp, &ub, td);
637         if (error == 0) {
638                 cvtstat(&ub, &oub);
639                 error = copyout((caddr_t)&oub, (caddr_t)uap->sb, sizeof (oub));
640         }
641         fdrop(fp, td);
642         return (error);
643 }
644 #endif /* COMPAT_43 || COMPAT_SUNOS */
645
646 /*
647  * Return status information about a file descriptor.
648  */
649 /* ARGSUSED */
650 int
651 fstat(struct fstat_args *uap)
652 {
653         struct thread *td = curthread;
654         struct proc *p = td->td_proc;
655         struct filedesc *fdp = p->p_fd;
656         struct file *fp;
657         struct stat ub;
658         int error;
659
660         KKASSERT(p);
661         fdp = p->p_fd;
662         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
663             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
664                 return (EBADF);
665         fhold(fp);
666         error = fo_stat(fp, &ub, td);
667         if (error == 0)
668                 error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
669         fdrop(fp, td);
670         return (error);
671 }
672
673 /*
674  * Return status information about a file descriptor.
675  */
676 /* ARGSUSED */
677 int
678 nfstat(struct nfstat_args *uap)
679 {
680         struct thread *td = curthread;
681         struct proc *p = td->td_proc;
682         struct filedesc *fdp;
683         struct file *fp;
684         struct stat ub;
685         struct nstat nub;
686         int error;
687
688         KKASSERT(p);
689         fdp = p->p_fd;
690         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
691             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
692                 return (EBADF);
693         fhold(fp);
694         error = fo_stat(fp, &ub, td);
695         if (error == 0) {
696                 cvtnstat(&ub, &nub);
697                 error = copyout((caddr_t)&nub, (caddr_t)uap->sb, sizeof (nub));
698         }
699         fdrop(fp, td);
700         return (error);
701 }
702
703 /*
704  * Return pathconf information about a file descriptor.
705  */
706 /* ARGSUSED */
707 int
708 fpathconf(struct fpathconf_args *uap)
709 {
710         struct thread *td = curthread;
711         struct proc *p = td->td_proc;
712         struct filedesc *fdp;
713         struct file *fp;
714         struct vnode *vp;
715         int error = 0;
716
717         KKASSERT(p);
718         fdp = p->p_fd;
719         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
720             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
721                 return (EBADF);
722
723         fhold(fp);
724
725         switch (fp->f_type) {
726         case DTYPE_PIPE:
727         case DTYPE_SOCKET:
728                 if (uap->name != _PC_PIPE_BUF) {
729                         error = EINVAL;
730                 } else {
731                         uap->sysmsg_result = PIPE_BUF;
732                         error = 0;
733                 }
734                 break;
735         case DTYPE_FIFO:
736         case DTYPE_VNODE:
737                 vp = (struct vnode *)fp->f_data;
738                 error = VOP_PATHCONF(vp, uap->name, uap->sysmsg_fds);
739                 break;
740         default:
741                 error = EOPNOTSUPP;
742                 break;
743         }
744         fdrop(fp, td);
745         return(error);
746 }
747
748 /*
749  * Allocate a file descriptor for the process.
750  */
751 static int fdexpand;
752 SYSCTL_INT(_debug, OID_AUTO, fdexpand, CTLFLAG_RD, &fdexpand, 0, "");
753
754 int
755 fdalloc(p, want, result)
756         struct proc *p;
757         int want;
758         int *result;
759 {
760         struct filedesc *fdp = p->p_fd;
761         int i;
762         int lim, last, nfiles;
763         struct file **newofile;
764         char *newofileflags;
765
766         /*
767          * Search for a free descriptor starting at the higher
768          * of want or fd_freefile.  If that fails, consider
769          * expanding the ofile array.
770          */
771         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
772         for (;;) {
773                 last = min(fdp->fd_nfiles, lim);
774                 if ((i = want) < fdp->fd_freefile)
775                         i = fdp->fd_freefile;
776                 for (; i < last; i++) {
777                         if (fdp->fd_ofiles[i] == NULL) {
778                                 fdp->fd_ofileflags[i] = 0;
779                                 if (i > fdp->fd_lastfile)
780                                         fdp->fd_lastfile = i;
781                                 if (want <= fdp->fd_freefile)
782                                         fdp->fd_freefile = i;
783                                 *result = i;
784                                 return (0);
785                         }
786                 }
787
788                 /*
789                  * No space in current array.  Expand?
790                  */
791                 if (fdp->fd_nfiles >= lim)
792                         return (EMFILE);
793                 if (fdp->fd_nfiles < NDEXTENT)
794                         nfiles = NDEXTENT;
795                 else
796                         nfiles = 2 * fdp->fd_nfiles;
797                 MALLOC(newofile, struct file **, nfiles * OFILESIZE,
798                     M_FILEDESC, M_WAITOK);
799
800                 /*
801                  * deal with file-table extend race that might have occured
802                  * when malloc was blocked.
803                  */
804                 if (fdp->fd_nfiles >= nfiles) {
805                         FREE(newofile, M_FILEDESC);
806                         continue;
807                 }
808                 newofileflags = (char *) &newofile[nfiles];
809                 /*
810                  * Copy the existing ofile and ofileflags arrays
811                  * and zero the new portion of each array.
812                  */
813                 bcopy(fdp->fd_ofiles, newofile,
814                         (i = sizeof(struct file *) * fdp->fd_nfiles));
815                 bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
816                 bcopy(fdp->fd_ofileflags, newofileflags,
817                         (i = sizeof(char) * fdp->fd_nfiles));
818                 bzero(newofileflags + i, nfiles * sizeof(char) - i);
819                 if (fdp->fd_nfiles > NDFILE)
820                         FREE(fdp->fd_ofiles, M_FILEDESC);
821                 fdp->fd_ofiles = newofile;
822                 fdp->fd_ofileflags = newofileflags;
823                 fdp->fd_nfiles = nfiles;
824                 fdexpand++;
825         }
826         return (0);
827 }
828
829 /*
830  * Check to see whether n user file descriptors
831  * are available to the process p.
832  */
833 int
834 fdavail(p, n)
835         struct proc *p;
836         int n;
837 {
838         struct filedesc *fdp = p->p_fd;
839         struct file **fpp;
840         int i, lim, last;
841
842         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfilesperproc);
843         if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
844                 return (1);
845
846         last = min(fdp->fd_nfiles, lim);
847         fpp = &fdp->fd_ofiles[fdp->fd_freefile];
848         for (i = last - fdp->fd_freefile; --i >= 0; fpp++) {
849                 if (*fpp == NULL && --n <= 0)
850                         return (1);
851         }
852         return (0);
853 }
854
855 /*
856  * falloc:
857  *      Create a new open file structure and allocate a file decriptor
858  *      for the process that refers to it.  If p is NULL, no descriptor
859  *      is allocated and the file pointer is returned unassociated with
860  *      any process.  resultfd is only used if p is not NULL and may
861  *      separately be NULL indicating that you don't need the returned fd.
862  */
863 int
864 falloc(struct proc *p, struct file **resultfp, int *resultfd)
865 {
866         struct file *fp, *fq;
867         int error, i;
868
869         if (nfiles >= maxfiles) {
870                 tablefull("file");
871                 return (ENFILE);
872         }
873         /*
874          * Allocate a new file descriptor.
875          * If the process has file descriptor zero open, add to the list
876          * of open files at that point, otherwise put it at the front of
877          * the list of open files.
878          */
879         nfiles++;
880         MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
881         bzero(fp, sizeof(struct file));
882
883         /*
884          * wait until after malloc (which may have blocked) returns before
885          * allocating the slot, else a race might have shrunk it if we had
886          * allocated it before the malloc.
887          */
888         i = -1;
889         if (p && (error = fdalloc(p, 0, &i))) {
890                 nfiles--;
891                 FREE(fp, M_FILE);
892                 return (error);
893         }
894         fp->f_count = 1;
895         fp->f_cred = crhold(p->p_ucred);
896         fp->f_ops = &badfileops;
897         fp->f_seqcount = 1;
898         if (p) {
899                 if ((fq = p->p_fd->fd_ofiles[0]) != NULL) {
900                         LIST_INSERT_AFTER(fq, fp, f_list);
901                 } else {
902                         LIST_INSERT_HEAD(&filehead, fp, f_list);
903                 }
904                 p->p_fd->fd_ofiles[i] = fp;
905         }
906         if (resultfp)
907                 *resultfp = fp;
908         if (resultfd)
909                 *resultfd = i;
910         return (0);
911 }
912
913 /*
914  * Free a file descriptor.
915  */
916 void
917 ffree(fp)
918         struct file *fp;
919 {
920         KASSERT((fp->f_count == 0), ("ffree: fp_fcount not 0!"));
921         LIST_REMOVE(fp, f_list);
922         crfree(fp->f_cred);
923         nfiles--;
924         FREE(fp, M_FILE);
925 }
926
927 /*
928  * Build a new filedesc structure.
929  */
930 struct filedesc *
931 fdinit(p)
932         struct proc *p;
933 {
934         struct filedesc0 *newfdp;
935         struct filedesc *fdp = p->p_fd;
936
937         MALLOC(newfdp, struct filedesc0 *, sizeof(struct filedesc0),
938             M_FILEDESC, M_WAITOK);
939         bzero(newfdp, sizeof(struct filedesc0));
940         newfdp->fd_fd.fd_cdir = fdp->fd_cdir;
941         if (newfdp->fd_fd.fd_cdir)
942                 VREF(newfdp->fd_fd.fd_cdir);
943         newfdp->fd_fd.fd_rdir = fdp->fd_rdir;
944         if (newfdp->fd_fd.fd_rdir)
945                 VREF(newfdp->fd_fd.fd_rdir);
946         newfdp->fd_fd.fd_jdir = fdp->fd_jdir;
947         if (newfdp->fd_fd.fd_jdir)
948                 VREF(newfdp->fd_fd.fd_jdir);
949
950         /* Create the file descriptor table. */
951         newfdp->fd_fd.fd_refcnt = 1;
952         newfdp->fd_fd.fd_cmask = cmask;
953         newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
954         newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
955         newfdp->fd_fd.fd_nfiles = NDFILE;
956         newfdp->fd_fd.fd_knlistsize = -1;
957
958         return (&newfdp->fd_fd);
959 }
960
961 /*
962  * Share a filedesc structure.
963  */
964 struct filedesc *
965 fdshare(p)
966         struct proc *p;
967 {
968         p->p_fd->fd_refcnt++;
969         return (p->p_fd);
970 }
971
972 /*
973  * Copy a filedesc structure.
974  */
975 struct filedesc *
976 fdcopy(p)
977         struct proc *p;
978 {
979         struct filedesc *newfdp, *fdp = p->p_fd;
980         struct file **fpp;
981         int i;
982
983         /* Certain daemons might not have file descriptors. */
984         if (fdp == NULL)
985                 return (NULL);
986
987         MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
988             M_FILEDESC, M_WAITOK);
989         bcopy(fdp, newfdp, sizeof(struct filedesc));
990         if (newfdp->fd_cdir)
991                 VREF(newfdp->fd_cdir);
992         if (newfdp->fd_rdir)
993                 VREF(newfdp->fd_rdir);
994         if (newfdp->fd_jdir)
995                 VREF(newfdp->fd_jdir);
996         newfdp->fd_refcnt = 1;
997
998         /*
999          * If the number of open files fits in the internal arrays
1000          * of the open file structure, use them, otherwise allocate
1001          * additional memory for the number of descriptors currently
1002          * in use.
1003          */
1004         if (newfdp->fd_lastfile < NDFILE) {
1005                 newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
1006                 newfdp->fd_ofileflags =
1007                     ((struct filedesc0 *) newfdp)->fd_dfileflags;
1008                 i = NDFILE;
1009         } else {
1010                 /*
1011                  * Compute the smallest multiple of NDEXTENT needed
1012                  * for the file descriptors currently in use,
1013                  * allowing the table to shrink.
1014                  */
1015                 i = newfdp->fd_nfiles;
1016                 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
1017                         i /= 2;
1018                 MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
1019                     M_FILEDESC, M_WAITOK);
1020                 newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
1021         }
1022         newfdp->fd_nfiles = i;
1023         bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
1024         bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
1025
1026         /*
1027          * kq descriptors cannot be copied.
1028          */
1029         if (newfdp->fd_knlistsize != -1) {
1030                 fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
1031                 for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
1032                         if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
1033                                 *fpp = NULL;
1034                                 if (i < newfdp->fd_freefile)
1035                                         newfdp->fd_freefile = i;
1036                         }
1037                         if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
1038                                 newfdp->fd_lastfile--;
1039                 }
1040                 newfdp->fd_knlist = NULL;
1041                 newfdp->fd_knlistsize = -1;
1042                 newfdp->fd_knhash = NULL;
1043                 newfdp->fd_knhashmask = 0;
1044         }
1045
1046         fpp = newfdp->fd_ofiles;
1047         for (i = newfdp->fd_lastfile; i-- >= 0; fpp++) {
1048                 if (*fpp != NULL)
1049                         fhold(*fpp);
1050         }
1051         return (newfdp);
1052 }
1053
1054 /*
1055  * Release a filedesc structure.
1056  */
1057 void
1058 fdfree(struct proc *p)
1059 {
1060         struct thread *td = p->p_thread;
1061         struct filedesc *fdp = p->p_fd;
1062         struct file **fpp;
1063         int i;
1064         struct filedesc_to_leader *fdtol;
1065         struct file *fp;
1066         struct vnode *vp;
1067         struct flock lf;
1068
1069         /* Certain daemons might not have file descriptors. */
1070         if (fdp == NULL)
1071                 return;
1072
1073         /* Check for special need to clear POSIX style locks */
1074         fdtol = p->p_fdtol;
1075         if (fdtol != NULL) {
1076                 KASSERT(fdtol->fdl_refcount > 0,
1077                         ("filedesc_to_refcount botch: fdl_refcount=%d",
1078                          fdtol->fdl_refcount));
1079                 if (fdtol->fdl_refcount == 1 &&
1080                     (p->p_leader->p_flag & P_ADVLOCK) != 0) {
1081                         i = 0;
1082                         fpp = fdp->fd_ofiles;
1083                         for (i = 0, fpp = fdp->fd_ofiles;
1084                              i < fdp->fd_lastfile;
1085                              i++, fpp++) {
1086                                 if (*fpp == NULL ||
1087                                     (*fpp)->f_type != DTYPE_VNODE)
1088                                         continue;
1089                                 fp = *fpp;
1090                                 fhold(fp);
1091                                 lf.l_whence = SEEK_SET;
1092                                 lf.l_start = 0;
1093                                 lf.l_len = 0;
1094                                 lf.l_type = F_UNLCK;
1095                                 vp = (struct vnode *)fp->f_data;
1096                                 (void) VOP_ADVLOCK(vp,
1097                                                    (caddr_t)p->p_leader,
1098                                                    F_UNLCK,
1099                                                    &lf,
1100                                                    F_POSIX);
1101                                 fdrop(fp, p->p_thread);
1102                                 fpp = fdp->fd_ofiles + i;
1103                         }
1104                 }
1105         retry:
1106                 if (fdtol->fdl_refcount == 1) {
1107                         if (fdp->fd_holdleaderscount > 0 &&
1108                             (p->p_leader->p_flag & P_ADVLOCK) != 0) {
1109                                 /*
1110                                  * close() or do_dup() has cleared a reference
1111                                  * in a shared file descriptor table.
1112                                  */
1113                                 fdp->fd_holdleaderswakeup = 1;
1114                                 tsleep(&fdp->fd_holdleaderscount,
1115                                        0, "fdlhold", 0);
1116                                 goto retry;
1117                         }
1118                         if (fdtol->fdl_holdcount > 0) {
1119                                 /* 
1120                                  * Ensure that fdtol->fdl_leader
1121                                  * remains valid in closef().
1122                                  */
1123                                 fdtol->fdl_wakeup = 1;
1124                                 tsleep(fdtol, 0, "fdlhold", 0);
1125                                 goto retry;
1126                         }
1127                 }
1128                 fdtol->fdl_refcount--;
1129                 if (fdtol->fdl_refcount == 0 &&
1130                     fdtol->fdl_holdcount == 0) {
1131                         fdtol->fdl_next->fdl_prev = fdtol->fdl_prev;
1132                         fdtol->fdl_prev->fdl_next = fdtol->fdl_next;
1133                 } else
1134                         fdtol = NULL;
1135                 p->p_fdtol = NULL;
1136                 if (fdtol != NULL)
1137                         FREE(fdtol, M_FILEDESC_TO_LEADER);
1138         }
1139         if (--fdp->fd_refcnt > 0)
1140                 return;
1141         /*
1142          * we are the last reference to the structure, we can
1143          * safely assume it will not change out from under us.
1144          */
1145         fpp = fdp->fd_ofiles;
1146         for (i = fdp->fd_lastfile; i-- >= 0; fpp++) {
1147                 if (*fpp)
1148                         (void) closef(*fpp, td);
1149         }
1150         if (fdp->fd_nfiles > NDFILE)
1151                 FREE(fdp->fd_ofiles, M_FILEDESC);
1152         if (fdp->fd_cdir)
1153                 vrele(fdp->fd_cdir);
1154         if (fdp->fd_rdir)
1155                 vrele(fdp->fd_rdir);
1156         if (fdp->fd_jdir)
1157                 vrele(fdp->fd_jdir);
1158         if (fdp->fd_knlist)
1159                 FREE(fdp->fd_knlist, M_KQUEUE);
1160         if (fdp->fd_knhash)
1161                 FREE(fdp->fd_knhash, M_KQUEUE);
1162         FREE(fdp, M_FILEDESC);
1163 }
1164
1165 /*
1166  * For setugid programs, we don't want to people to use that setugidness
1167  * to generate error messages which write to a file which otherwise would
1168  * otherwise be off-limits to the process.
1169  *
1170  * This is a gross hack to plug the hole.  A better solution would involve
1171  * a special vop or other form of generalized access control mechanism.  We
1172  * go ahead and just reject all procfs file systems accesses as dangerous.
1173  *
1174  * Since setugidsafety calls this only for fd 0, 1 and 2, this check is
1175  * sufficient.  We also don't for check setugidness since we know we are.
1176  */
1177 static int
1178 is_unsafe(struct file *fp)
1179 {
1180         if (fp->f_type == DTYPE_VNODE && 
1181             ((struct vnode *)(fp->f_data))->v_tag == VT_PROCFS)
1182                 return (1);
1183         return (0);
1184 }
1185
1186 /*
1187  * Make this setguid thing safe, if at all possible.
1188  */
1189 void
1190 setugidsafety(struct proc *p)
1191 {
1192         struct thread *td = p->p_thread;
1193         struct filedesc *fdp = p->p_fd;
1194         int i;
1195
1196         /* Certain daemons might not have file descriptors. */
1197         if (fdp == NULL)
1198                 return;
1199
1200         /*
1201          * note: fdp->fd_ofiles may be reallocated out from under us while
1202          * we are blocked in a close.  Be careful!
1203          */
1204         for (i = 0; i <= fdp->fd_lastfile; i++) {
1205                 if (i > 2)
1206                         break;
1207                 if (fdp->fd_ofiles[i] && is_unsafe(fdp->fd_ofiles[i])) {
1208                         struct file *fp;
1209
1210 #if 0
1211                         if ((fdp->fd_ofileflags[i] & UF_MAPPED) != 0)
1212                                 (void) munmapfd(p, i);
1213 #endif
1214                         if (i < fdp->fd_knlistsize)
1215                                 knote_fdclose(p, i);
1216                         /*
1217                          * NULL-out descriptor prior to close to avoid
1218                          * a race while close blocks.
1219                          */
1220                         fp = fdp->fd_ofiles[i];
1221                         fdp->fd_ofiles[i] = NULL;
1222                         fdp->fd_ofileflags[i] = 0;
1223                         if (i < fdp->fd_freefile)
1224                                 fdp->fd_freefile = i;
1225                         (void) closef(fp, td);
1226                 }
1227         }
1228         while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
1229                 fdp->fd_lastfile--;
1230 }
1231
1232 /*
1233  * Close any files on exec?
1234  */
1235 void
1236 fdcloseexec(struct proc *p)
1237 {
1238         struct thread *td = p->p_thread;
1239         struct filedesc *fdp = p->p_fd;
1240         int i;
1241
1242         /* Certain daemons might not have file descriptors. */
1243         if (fdp == NULL)
1244                 return;
1245
1246         /*
1247          * We cannot cache fd_ofiles or fd_ofileflags since operations
1248          * may block and rip them out from under us.
1249          */
1250         for (i = 0; i <= fdp->fd_lastfile; i++) {
1251                 if (fdp->fd_ofiles[i] != NULL &&
1252                     (fdp->fd_ofileflags[i] & UF_EXCLOSE)) {
1253                         struct file *fp;
1254
1255 #if 0
1256                         if (fdp->fd_ofileflags[i] & UF_MAPPED)
1257                                 (void) munmapfd(p, i);
1258 #endif
1259                         if (i < fdp->fd_knlistsize)
1260                                 knote_fdclose(p, i);
1261                         /*
1262                          * NULL-out descriptor prior to close to avoid
1263                          * a race while close blocks.
1264                          */
1265                         fp = fdp->fd_ofiles[i];
1266                         fdp->fd_ofiles[i] = NULL;
1267                         fdp->fd_ofileflags[i] = 0;
1268                         if (i < fdp->fd_freefile)
1269                                 fdp->fd_freefile = i;
1270                         (void) closef(fp, td);
1271                 }
1272         }
1273         while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
1274                 fdp->fd_lastfile--;
1275 }
1276
1277 /*
1278  * It is unsafe for set[ug]id processes to be started with file
1279  * descriptors 0..2 closed, as these descriptors are given implicit
1280  * significance in the Standard C library.  fdcheckstd() will create a
1281  * descriptor referencing /dev/null for each of stdin, stdout, and
1282  * stderr that is not already open.
1283  */
1284 int
1285 fdcheckstd(struct proc *p)
1286 {
1287         struct thread *td = p->p_thread;
1288         struct nameidata nd;
1289         struct filedesc *fdp;
1290         struct file *fp;
1291         register_t retval;
1292         int fd, i, error, flags, devnull;
1293
1294        fdp = p->p_fd;
1295        if (fdp == NULL)
1296                return (0);
1297        devnull = -1;
1298        error = 0;
1299        for (i = 0; i < 3; i++) {
1300                if (fdp->fd_ofiles[i] != NULL)
1301                        continue;
1302                if (devnull < 0) {
1303                        error = falloc(p, &fp, &fd);
1304                        if (error != 0)
1305                                break;
1306                        NDINIT(&nd, NAMEI_LOOKUP, CNP_FOLLOW, UIO_SYSSPACE, 
1307                            "/dev/null", td);
1308                        flags = FREAD | FWRITE;
1309                        error = vn_open(&nd, flags, 0);
1310                        if (error != 0) {
1311                                fdp->fd_ofiles[i] = NULL;
1312                                fdrop(fp, td);
1313                                break;
1314                        }
1315                        NDFREE(&nd, NDF_ONLY_PNBUF);
1316                        fp->f_data = (caddr_t)nd.ni_vp;
1317                        fp->f_flag = flags;
1318                        fp->f_ops = &vnops;
1319                        fp->f_type = DTYPE_VNODE;
1320                        VOP_UNLOCK(nd.ni_vp, 0, td);
1321                        devnull = fd;
1322                } else {
1323                        error = fdalloc(p, 0, &fd);
1324                        if (error != 0)
1325                                break;
1326                        error = do_dup(fdp, devnull, fd, &retval, p);
1327                        if (error != 0)
1328                                break;
1329                }
1330        }
1331        return (error);
1332 }
1333
1334 /*
1335  * Internal form of close.
1336  * Decrement reference count on file structure.
1337  * Note: td and/or p may be NULL when closing a file
1338  * that was being passed in a message.
1339  */
1340 int
1341 closef(struct file *fp, struct thread *td)
1342 {
1343         struct vnode *vp;
1344         struct flock lf;
1345         struct filedesc_to_leader *fdtol;
1346         struct proc *p;
1347
1348         if (fp == NULL)
1349                 return (0);
1350         if (td == NULL) {
1351                 td = curthread;
1352                 p = NULL;               /* allow no proc association */
1353         } else {
1354                 p = td->td_proc;        /* can also be NULL */
1355         }
1356         /*
1357          * POSIX record locking dictates that any close releases ALL
1358          * locks owned by this process.  This is handled by setting
1359          * a flag in the unlock to free ONLY locks obeying POSIX
1360          * semantics, and not to free BSD-style file locks.
1361          * If the descriptor was in a message, POSIX-style locks
1362          * aren't passed with the descriptor.
1363          */
1364         if (p != NULL && 
1365             fp->f_type == DTYPE_VNODE) {
1366                 if ((p->p_leader->p_flag & P_ADVLOCK) != 0) {
1367                         lf.l_whence = SEEK_SET;
1368                         lf.l_start = 0;
1369                         lf.l_len = 0;
1370                         lf.l_type = F_UNLCK;
1371                         vp = (struct vnode *)fp->f_data;
1372                         (void) VOP_ADVLOCK(vp, (caddr_t)p->p_leader, F_UNLCK,
1373                                            &lf, F_POSIX);
1374                 }
1375                 fdtol = p->p_fdtol;
1376                 if (fdtol != NULL) {
1377                         /*
1378                          * Handle special case where file descriptor table
1379                          * is shared between multiple process leaders.
1380                          */
1381                         for (fdtol = fdtol->fdl_next;
1382                              fdtol != p->p_fdtol;
1383                              fdtol = fdtol->fdl_next) {
1384                                 if ((fdtol->fdl_leader->p_flag &
1385                                      P_ADVLOCK) == 0)
1386                                         continue;
1387                                 fdtol->fdl_holdcount++;
1388                                 lf.l_whence = SEEK_SET;
1389                                 lf.l_start = 0;
1390                                 lf.l_len = 0;
1391                                 lf.l_type = F_UNLCK;
1392                                 vp = (struct vnode *)fp->f_data;
1393                                 (void) VOP_ADVLOCK(vp,
1394                                                    (caddr_t)p->p_leader,
1395                                                    F_UNLCK, &lf, F_POSIX);
1396                                 fdtol->fdl_holdcount--;
1397                                 if (fdtol->fdl_holdcount == 0 &&
1398                                     fdtol->fdl_wakeup != 0) {
1399                                         fdtol->fdl_wakeup = 0;
1400                                         wakeup(fdtol);
1401                                 }
1402                         }
1403                 }
1404         }
1405         return (fdrop(fp, td));
1406 }
1407
1408 int
1409 fdrop(struct file *fp, struct thread *td)
1410 {
1411         struct flock lf;
1412         struct vnode *vp;
1413         int error;
1414
1415         if (--fp->f_count > 0)
1416                 return (0);
1417         if (fp->f_count < 0)
1418                 panic("fdrop: count < 0");
1419         if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
1420                 lf.l_whence = SEEK_SET;
1421                 lf.l_start = 0;
1422                 lf.l_len = 0;
1423                 lf.l_type = F_UNLCK;
1424                 vp = (struct vnode *)fp->f_data;
1425                 (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
1426         }
1427         if (fp->f_ops != &badfileops)
1428                 error = fo_close(fp, td);
1429         else
1430                 error = 0;
1431         ffree(fp);
1432         return (error);
1433 }
1434
1435 /*
1436  * Apply an advisory lock on a file descriptor.
1437  *
1438  * Just attempt to get a record lock of the requested type on
1439  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
1440  */
1441 /* ARGSUSED */
1442 int
1443 flock(struct flock_args *uap)
1444 {
1445         struct proc *p = curproc;
1446         struct filedesc *fdp = p->p_fd;
1447         struct file *fp;
1448         struct vnode *vp;
1449         struct flock lf;
1450
1451         if ((unsigned)uap->fd >= fdp->fd_nfiles ||
1452             (fp = fdp->fd_ofiles[uap->fd]) == NULL)
1453                 return (EBADF);
1454         if (fp->f_type != DTYPE_VNODE)
1455                 return (EOPNOTSUPP);
1456         vp = (struct vnode *)fp->f_data;
1457         lf.l_whence = SEEK_SET;
1458         lf.l_start = 0;
1459         lf.l_len = 0;
1460         if (uap->how & LOCK_UN) {
1461                 lf.l_type = F_UNLCK;
1462                 fp->f_flag &= ~FHASLOCK;
1463                 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
1464         }
1465         if (uap->how & LOCK_EX)
1466                 lf.l_type = F_WRLCK;
1467         else if (uap->how & LOCK_SH)
1468                 lf.l_type = F_RDLCK;
1469         else
1470                 return (EBADF);
1471         fp->f_flag |= FHASLOCK;
1472         if (uap->how & LOCK_NB)
1473                 return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
1474         return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
1475 }
1476
1477 /*
1478  * File Descriptor pseudo-device driver (/dev/fd/).
1479  *
1480  * Opening minor device N dup()s the file (if any) connected to file
1481  * descriptor N belonging to the calling process.  Note that this driver
1482  * consists of only the ``open()'' routine, because all subsequent
1483  * references to this file will be direct to the other driver.
1484  */
1485 /* ARGSUSED */
1486 static int
1487 fdopen(dev_t dev, int mode, int type, struct thread *td)
1488 {
1489         KKASSERT(td->td_proc != NULL);
1490
1491         /*
1492          * XXX Kludge: set curproc->p_dupfd to contain the value of the
1493          * the file descriptor being sought for duplication. The error
1494          * return ensures that the vnode for this device will be released
1495          * by vn_open. Open will detect this special error and take the
1496          * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
1497          * will simply report the error.
1498          */
1499         td->td_proc->p_dupfd = minor(dev);
1500         return (ENODEV);
1501 }
1502
1503 /*
1504  * Duplicate the specified descriptor to a free descriptor.
1505  */
1506 int
1507 dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode, int error)
1508 {
1509         struct file *wfp;
1510         struct file *fp;
1511
1512         /*
1513          * If the to-be-dup'd fd number is greater than the allowed number
1514          * of file descriptors, or the fd to be dup'd has already been
1515          * closed, then reject.
1516          */
1517         if ((u_int)dfd >= fdp->fd_nfiles ||
1518             (wfp = fdp->fd_ofiles[dfd]) == NULL) {
1519                 return (EBADF);
1520         }
1521
1522         /*
1523          * There are two cases of interest here.
1524          *
1525          * For ENODEV simply dup (dfd) to file descriptor
1526          * (indx) and return.
1527          *
1528          * For ENXIO steal away the file structure from (dfd) and
1529          * store it in (indx).  (dfd) is effectively closed by
1530          * this operation.
1531          *
1532          * Any other error code is just returned.
1533          */
1534         switch (error) {
1535         case ENODEV:
1536                 /*
1537                  * Check that the mode the file is being opened for is a
1538                  * subset of the mode of the existing descriptor.
1539                  */
1540                 if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
1541                         return (EACCES);
1542                 fp = fdp->fd_ofiles[indx];
1543 #if 0
1544                 if (fp && fdp->fd_ofileflags[indx] & UF_MAPPED)
1545                         (void) munmapfd(p, indx);
1546 #endif
1547                 fdp->fd_ofiles[indx] = wfp;
1548                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1549                 fhold(wfp);
1550                 if (indx > fdp->fd_lastfile)
1551                         fdp->fd_lastfile = indx;
1552                 /*
1553                  * we now own the reference to fp that the ofiles[] array
1554                  * used to own.  Release it.
1555                  */
1556                 if (fp)
1557                         fdrop(fp, curthread);
1558                 return (0);
1559
1560         case ENXIO:
1561                 /*
1562                  * Steal away the file pointer from dfd, and stuff it into indx.
1563                  */
1564                 fp = fdp->fd_ofiles[indx];
1565 #if 0
1566                 if (fp && fdp->fd_ofileflags[indx] & UF_MAPPED)
1567                         (void) munmapfd(p, indx);
1568 #endif
1569                 fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
1570                 fdp->fd_ofiles[dfd] = NULL;
1571                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
1572                 fdp->fd_ofileflags[dfd] = 0;
1573
1574                 /*
1575                  * we now own the reference to fp that the ofiles[] array
1576                  * used to own.  Release it.
1577                  */
1578                 if (fp)
1579                         fdrop(fp, curthread);
1580                 /*
1581                  * Complete the clean up of the filedesc structure by
1582                  * recomputing the various hints.
1583                  */
1584                 if (indx > fdp->fd_lastfile) {
1585                         fdp->fd_lastfile = indx;
1586                 } else {
1587                         while (fdp->fd_lastfile > 0 &&
1588                            fdp->fd_ofiles[fdp->fd_lastfile] == NULL) {
1589                                 fdp->fd_lastfile--;
1590                         }
1591                         if (dfd < fdp->fd_freefile)
1592                                 fdp->fd_freefile = dfd;
1593                 }
1594                 return (0);
1595
1596         default:
1597                 return (error);
1598         }
1599         /* NOTREACHED */
1600 }
1601
1602
1603 struct filedesc_to_leader *
1604 filedesc_to_leader_alloc(struct filedesc_to_leader *old,
1605                          struct proc *leader)
1606 {
1607         struct filedesc_to_leader *fdtol;
1608         
1609         MALLOC(fdtol, struct filedesc_to_leader *,
1610                sizeof(struct filedesc_to_leader),
1611                M_FILEDESC_TO_LEADER,
1612                M_WAITOK);
1613         fdtol->fdl_refcount = 1;
1614         fdtol->fdl_holdcount = 0;
1615         fdtol->fdl_wakeup = 0;
1616         fdtol->fdl_leader = leader;
1617         if (old != NULL) {
1618                 fdtol->fdl_next = old->fdl_next;
1619                 fdtol->fdl_prev = old;
1620                 old->fdl_next = fdtol;
1621                 fdtol->fdl_next->fdl_prev = fdtol;
1622         } else {
1623                 fdtol->fdl_next = fdtol;
1624                 fdtol->fdl_prev = fdtol;
1625         }
1626         return fdtol;
1627 }
1628
1629 /*
1630  * Get file structures.
1631  */
1632 static int
1633 sysctl_kern_file(SYSCTL_HANDLER_ARGS)
1634 {
1635         int error;
1636         struct file *fp;
1637
1638         if (!req->oldptr) {
1639                 /*
1640                  * overestimate by 10 files
1641                  */
1642                 return (SYSCTL_OUT(req, 0, sizeof(filehead) + 
1643                                 (nfiles + 10) * sizeof(struct file)));
1644         }
1645
1646         error = SYSCTL_OUT(req, (caddr_t)&filehead, sizeof(filehead));
1647         if (error)
1648                 return (error);
1649
1650         /*
1651          * followed by an array of file structures
1652          */
1653         LIST_FOREACH(fp, &filehead, f_list) {
1654                 error = SYSCTL_OUT(req, (caddr_t)fp, sizeof (struct file));
1655                 if (error)
1656                         return (error);
1657         }
1658         return (0);
1659 }
1660
1661 SYSCTL_PROC(_kern, KERN_FILE, file, CTLTYPE_OPAQUE|CTLFLAG_RD,
1662     0, 0, sysctl_kern_file, "S,file", "Entire file table");
1663
1664 SYSCTL_INT(_kern, KERN_MAXFILESPERPROC, maxfilesperproc, CTLFLAG_RW, 
1665     &maxfilesperproc, 0, "Maximum files allowed open per process");
1666
1667 SYSCTL_INT(_kern, KERN_MAXFILES, maxfiles, CTLFLAG_RW, 
1668     &maxfiles, 0, "Maximum number of files");
1669
1670 SYSCTL_INT(_kern, OID_AUTO, openfiles, CTLFLAG_RD, 
1671         &nfiles, 0, "System-wide number of open files");
1672
1673 static void
1674 fildesc_drvinit(void *unused)
1675 {
1676         int fd;
1677
1678         for (fd = 0; fd < NUMFDESC; fd++)
1679                 make_dev(&fildesc_cdevsw, fd,
1680                     UID_BIN, GID_BIN, 0666, "fd/%d", fd);
1681         make_dev(&fildesc_cdevsw, 0, UID_ROOT, GID_WHEEL, 0666, "stdin");
1682         make_dev(&fildesc_cdevsw, 1, UID_ROOT, GID_WHEEL, 0666, "stdout");
1683         make_dev(&fildesc_cdevsw, 2, UID_ROOT, GID_WHEEL, 0666, "stderr");
1684 }
1685
1686 struct fileops badfileops = {
1687         NULL,   /* port */
1688         0,      /* autoq */
1689         badfo_readwrite,
1690         badfo_readwrite,
1691         badfo_ioctl,
1692         badfo_poll,
1693         badfo_kqfilter,
1694         badfo_stat,
1695         badfo_close
1696 };
1697
1698 static int
1699 badfo_readwrite(
1700         struct file *fp,
1701         struct uio *uio,
1702         struct ucred *cred,
1703         int flags,
1704         struct thread *td
1705 ) {
1706         return (EBADF);
1707 }
1708
1709 static int
1710 badfo_ioctl(struct file *fp, u_long com, caddr_t data, struct thread *td)
1711 {
1712         return (EBADF);
1713 }
1714
1715 static int
1716 badfo_poll(struct file *fp, int events, struct ucred *cred, struct thread *td)
1717 {
1718         return (0);
1719 }
1720
1721 static int
1722 badfo_kqfilter(struct file *fp, struct knote *kn)
1723 {
1724         return (0);
1725 }
1726
1727 static int
1728 badfo_stat(struct file *fp, struct stat *sb, struct thread *td)
1729 {
1730         return (EBADF);
1731 }
1732
1733 static int
1734 badfo_close(struct file *fp, struct thread *td)
1735 {
1736         return (EBADF);
1737 }
1738
1739 SYSINIT(fildescdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,
1740                                         fildesc_drvinit,NULL)