[BACK]Return to kern_descrip.c CVS log [TXT][DIR] Up to [local] / sys / kern

Annotation of sys/kern/kern_descrip.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: kern_descrip.c,v 1.76 2007/03/15 10:22:30 art Exp $   */
                      2: /*     $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $       */
                      3:
                      4: /*
                      5:  * Copyright (c) 1982, 1986, 1989, 1991, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  * (c) UNIX System Laboratories, Inc.
                      8:  * All or some portions of this file are derived from material licensed
                      9:  * to the University of California by American Telephone and Telegraph
                     10:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     11:  * the permission of UNIX System Laboratories, Inc.
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. Neither the name of the University nor the names of its contributors
                     22:  *    may be used to endorse or promote products derived from this software
                     23:  *    without specific prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     35:  * SUCH DAMAGE.
                     36:  *
                     37:  *     @(#)kern_descrip.c      8.6 (Berkeley) 4/19/94
                     38:  */
                     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/filedesc.h>
                     43: #include <sys/kernel.h>
                     44: #include <sys/vnode.h>
                     45: #include <sys/proc.h>
                     46: #include <sys/file.h>
                     47: #include <sys/socket.h>
                     48: #include <sys/socketvar.h>
                     49: #include <sys/stat.h>
                     50: #include <sys/ioctl.h>
                     51: #include <sys/fcntl.h>
                     52: #include <sys/malloc.h>
                     53: #include <sys/syslog.h>
                     54: #include <sys/ucred.h>
                     55: #include <sys/unistd.h>
                     56: #include <sys/resourcevar.h>
                     57: #include <sys/conf.h>
                     58: #include <sys/mount.h>
                     59: #include <sys/syscallargs.h>
                     60: #include <sys/event.h>
                     61: #include <sys/pool.h>
                     62:
                     63: #include <uvm/uvm_extern.h>
                     64:
                     65: #include <sys/pipe.h>
                     66:
                     67: /*
                     68:  * Descriptor management.
                     69:  */
                     70: struct filelist filehead;      /* head of list of open files */
                     71: int nfiles;                    /* actual number of open files */
                     72:
                     73: static __inline void fd_used(struct filedesc *, int);
                     74: static __inline void fd_unused(struct filedesc *, int);
                     75: static __inline int find_next_zero(u_int *, int, u_int);
                     76: int finishdup(struct proc *, struct file *, int, int, register_t *);
                     77: int find_last_set(struct filedesc *, int);
                     78:
                     79: struct pool file_pool;
                     80: struct pool fdesc_pool;
                     81:
                     82: void
                     83: filedesc_init(void)
                     84: {
                     85:        pool_init(&file_pool, sizeof(struct file), 0, 0, 0, "filepl",
                     86:                &pool_allocator_nointr);
                     87:        pool_init(&fdesc_pool, sizeof(struct filedesc0), 0, 0, 0, "fdescpl",
                     88:                &pool_allocator_nointr);
                     89:        LIST_INIT(&filehead);
                     90: }
                     91:
                     92: static __inline int
                     93: find_next_zero (u_int *bitmap, int want, u_int bits)
                     94: {
                     95:        int i, off, maxoff;
                     96:        u_int sub;
                     97:
                     98:        if (want > bits)
                     99:                return -1;
                    100:
                    101:        off = want >> NDENTRYSHIFT;
                    102:        i = want & NDENTRYMASK;
                    103:        if (i) {
                    104:                sub = bitmap[off] | ((u_int)~0 >> (NDENTRIES - i));
                    105:                if (sub != ~0)
                    106:                        goto found;
                    107:                off++;
                    108:        }
                    109:
                    110:        maxoff = NDLOSLOTS(bits);
                    111:        while (off < maxoff) {
                    112:                if ((sub = bitmap[off]) != ~0)
                    113:                        goto found;
                    114:                off++;
                    115:        }
                    116:
                    117:        return -1;
                    118:
                    119:  found:
                    120:        return (off << NDENTRYSHIFT) + ffs(~sub) - 1;
                    121: }
                    122:
                    123: int
                    124: find_last_set(struct filedesc *fd, int last)
                    125: {
                    126:        int off, i;
                    127:        struct file **ofiles = fd->fd_ofiles;
                    128:        u_int *bitmap = fd->fd_lomap;
                    129:
                    130:        off = (last - 1) >> NDENTRYSHIFT;
                    131:
                    132:        while (off >= 0 && !bitmap[off])
                    133:                off--;
                    134:        if (off < 0)
                    135:                return 0;
                    136:
                    137:        i = ((off + 1) << NDENTRYSHIFT) - 1;
                    138:        if (i >= last)
                    139:                i = last - 1;
                    140:
                    141:        while (i > 0 && ofiles[i] == NULL)
                    142:                i--;
                    143:        return i;
                    144: }
                    145:
                    146: static __inline void
                    147: fd_used(struct filedesc *fdp, int fd)
                    148: {
                    149:        u_int off = fd >> NDENTRYSHIFT;
                    150:
                    151:        fdp->fd_lomap[off] |= 1 << (fd & NDENTRYMASK);
                    152:        if (fdp->fd_lomap[off] == ~0)
                    153:                fdp->fd_himap[off >> NDENTRYSHIFT] |= 1 << (off & NDENTRYMASK);
                    154:
                    155:        if (fd > fdp->fd_lastfile)
                    156:                fdp->fd_lastfile = fd;
                    157: }
                    158:
                    159: static __inline void
                    160: fd_unused(struct filedesc *fdp, int fd)
                    161: {
                    162:        u_int off = fd >> NDENTRYSHIFT;
                    163:
                    164:        if (fd < fdp->fd_freefile)
                    165:                fdp->fd_freefile = fd;
                    166:
                    167:        if (fdp->fd_lomap[off] == ~0)
                    168:                fdp->fd_himap[off >> NDENTRYSHIFT] &= ~(1 << (off & NDENTRYMASK));
                    169:        fdp->fd_lomap[off] &= ~(1 << (fd & NDENTRYMASK));
                    170:
                    171: #ifdef DIAGNOSTIC
                    172:        if (fd > fdp->fd_lastfile)
                    173:                panic("fd_unused: fd_lastfile inconsistent");
                    174: #endif
                    175:        if (fd == fdp->fd_lastfile)
                    176:                fdp->fd_lastfile = find_last_set(fdp, fd);
                    177: }
                    178:
                    179: struct file *
                    180: fd_getfile(struct filedesc *fdp, int fd)
                    181: {
                    182:        struct file *fp;
                    183:
                    184:        if ((u_int)fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
                    185:                return (NULL);
                    186:
                    187:        if (!FILE_IS_USABLE(fp))
                    188:                return (NULL);
                    189:
                    190:        return (fp);
                    191: }
                    192:
                    193: /*
                    194:  * System calls on descriptors.
                    195:  */
                    196:
                    197: /*
                    198:  * Duplicate a file descriptor.
                    199:  */
                    200: /* ARGSUSED */
                    201: int
                    202: sys_dup(struct proc *p, void *v, register_t *retval)
                    203: {
                    204:        struct sys_dup_args /* {
                    205:                syscallarg(int) fd;
                    206:        } */ *uap = v;
                    207:        struct filedesc *fdp = p->p_fd;
                    208:        int old = SCARG(uap, fd);
                    209:        struct file *fp;
                    210:        int new;
                    211:        int error;
                    212:
                    213: restart:
                    214:        if ((fp = fd_getfile(fdp, old)) == NULL)
                    215:                return (EBADF);
                    216:        FREF(fp);
                    217:        fdplock(fdp);
                    218:        if ((error = fdalloc(p, 0, &new)) != 0) {
                    219:                FRELE(fp);
                    220:                if (error == ENOSPC) {
                    221:                        fdexpand(p);
                    222:                        fdpunlock(fdp);
                    223:                        goto restart;
                    224:                }
                    225:                goto out;
                    226:        }
                    227:        error = finishdup(p, fp, old, new, retval);
                    228:
                    229: out:
                    230:        fdpunlock(fdp);
                    231:        return (error);
                    232: }
                    233:
                    234: /*
                    235:  * Duplicate a file descriptor to a particular value.
                    236:  */
                    237: /* ARGSUSED */
                    238: int
                    239: sys_dup2(struct proc *p, void *v, register_t *retval)
                    240: {
                    241:        struct sys_dup2_args /* {
                    242:                syscallarg(int) from;
                    243:                syscallarg(int) to;
                    244:        } */ *uap = v;
                    245:        int old = SCARG(uap, from), new = SCARG(uap, to);
                    246:        struct filedesc *fdp = p->p_fd;
                    247:        struct file *fp;
                    248:        int i, error;
                    249:
                    250: restart:
                    251:        if ((fp = fd_getfile(fdp, old)) == NULL)
                    252:                return (EBADF);
                    253:        if ((u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
                    254:            (u_int)new >= maxfiles)
                    255:                return (EBADF);
                    256:        if (old == new) {
                    257:                /*
                    258:                 * NOTE! This doesn't clear the close-on-exec flag. This might
                    259:                 * or might not be the intended behavior from the start, but
                    260:                 * this is what everyone else does.
                    261:                 */
                    262:                *retval = new;
                    263:                return (0);
                    264:        }
                    265:        FREF(fp);
                    266:        fdplock(fdp);
                    267:        if (new >= fdp->fd_nfiles) {
                    268:                if ((error = fdalloc(p, new, &i)) != 0) {
                    269:                        FRELE(fp);
                    270:                        if (error == ENOSPC) {
                    271:                                fdexpand(p);
                    272:                                fdpunlock(fdp);
                    273:                                goto restart;
                    274:                        }
                    275:                        goto out;
                    276:                }
                    277:                if (new != i)
                    278:                        panic("dup2: fdalloc");
                    279:        }
                    280:        /* finishdup() does FRELE */
                    281:        error = finishdup(p, fp, old, new, retval);
                    282:
                    283: out:
                    284:        fdpunlock(fdp);
                    285:        return (error);
                    286: }
                    287:
                    288: /*
                    289:  * The file control system call.
                    290:  */
                    291: /* ARGSUSED */
                    292: int
                    293: sys_fcntl(struct proc *p, void *v, register_t *retval)
                    294: {
                    295:        struct sys_fcntl_args /* {
                    296:                syscallarg(int) fd;
                    297:                syscallarg(int) cmd;
                    298:                syscallarg(void *) arg;
                    299:        } */ *uap = v;
                    300:        int fd = SCARG(uap, fd);
                    301:        struct filedesc *fdp = p->p_fd;
                    302:        struct file *fp;
                    303:        struct vnode *vp;
                    304:        int i, tmp, newmin, flg = F_POSIX;
                    305:        struct flock fl;
                    306:        int error = 0;
                    307:
                    308: restart:
                    309:        if ((fp = fd_getfile(fdp, fd)) == NULL)
                    310:                return (EBADF);
                    311:        FREF(fp);
                    312:        switch (SCARG(uap, cmd)) {
                    313:
                    314:        case F_DUPFD:
                    315:                newmin = (long)SCARG(uap, arg);
                    316:                if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
                    317:                    (u_int)newmin >= maxfiles) {
                    318:                        error = EINVAL;
                    319:                        break;
                    320:                }
                    321:                fdplock(fdp);
                    322:                if ((error = fdalloc(p, newmin, &i)) != 0) {
                    323:                        if (error == ENOSPC) {
                    324:                                fdexpand(p);
                    325:                                FRELE(fp);
                    326:                                fdpunlock(fdp);
                    327:                                goto restart;
                    328:                        }
                    329:                }
                    330:                /* finishdup will FRELE for us. */
                    331:                if (!error)
                    332:                        error = finishdup(p, fp, fd, i, retval);
                    333:                else
                    334:                        FRELE(fp);
                    335:
                    336:                fdpunlock(fdp);
                    337:                return (error);
                    338:
                    339:        case F_GETFD:
                    340:                *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;
                    341:                break;
                    342:
                    343:        case F_SETFD:
                    344:                if ((long)SCARG(uap, arg) & 1)
                    345:                        fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
                    346:                else
                    347:                        fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
                    348:                break;
                    349:
                    350:        case F_GETFL:
                    351:                *retval = OFLAGS(fp->f_flag);
                    352:                break;
                    353:
                    354:        case F_SETFL:
                    355:                fp->f_flag &= ~FCNTLFLAGS;
                    356:                fp->f_flag |= FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
                    357:                tmp = fp->f_flag & FNONBLOCK;
                    358:                error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
                    359:                if (error)
                    360:                        break;
                    361:                tmp = fp->f_flag & FASYNC;
                    362:                error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
                    363:                if (!error)
                    364:                        break;
                    365:                fp->f_flag &= ~FNONBLOCK;
                    366:                tmp = 0;
                    367:                (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
                    368:                break;
                    369:
                    370:        case F_GETOWN:
                    371:                if (fp->f_type == DTYPE_SOCKET) {
                    372:                        *retval = ((struct socket *)fp->f_data)->so_pgid;
                    373:                        break;
                    374:                }
                    375:                error = (*fp->f_ops->fo_ioctl)
                    376:                        (fp, TIOCGPGRP, (caddr_t)&tmp, p);
                    377:                *retval = -tmp;
                    378:                break;
                    379:
                    380:        case F_SETOWN:
                    381:                if (fp->f_type == DTYPE_SOCKET) {
                    382:                        struct socket *so = (struct socket *)fp->f_data;
                    383:
                    384:                        so->so_pgid = (long)SCARG(uap, arg);
                    385:                        so->so_siguid = p->p_cred->p_ruid;
                    386:                        so->so_sigeuid = p->p_ucred->cr_uid;
                    387:                        break;
                    388:                }
                    389:                if ((long)SCARG(uap, arg) <= 0) {
                    390:                        SCARG(uap, arg) = (void *)(-(long)SCARG(uap, arg));
                    391:                } else {
                    392:                        struct proc *p1 = pfind((long)SCARG(uap, arg));
                    393:                        if (p1 == 0) {
                    394:                                error = ESRCH;
                    395:                                break;
                    396:                        }
                    397:                        SCARG(uap, arg) = (void *)(long)p1->p_pgrp->pg_id;
                    398:                }
                    399:                error = ((*fp->f_ops->fo_ioctl)
                    400:                        (fp, TIOCSPGRP, (caddr_t)&SCARG(uap, arg), p));
                    401:                break;
                    402:
                    403:        case F_SETLKW:
                    404:                flg |= F_WAIT;
                    405:                /* FALLTHROUGH */
                    406:
                    407:        case F_SETLK:
                    408:                if (fp->f_type != DTYPE_VNODE) {
                    409:                        error = EBADF;
                    410:                        break;
                    411:                }
                    412:                vp = (struct vnode *)fp->f_data;
                    413:                /* Copy in the lock structure */
                    414:                error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl,
                    415:                    sizeof (fl));
                    416:                if (error)
                    417:                        break;
                    418:                if (fl.l_whence == SEEK_CUR) {
                    419:                        if (fl.l_start == 0 && fl.l_len < 0) {
                    420:                                /* lockf(3) compliance hack */
                    421:                                fl.l_len = -fl.l_len;
                    422:                                fl.l_start = fp->f_offset - fl.l_len;
                    423:                        } else
                    424:                                fl.l_start += fp->f_offset;
                    425:                }
                    426:                switch (fl.l_type) {
                    427:
                    428:                case F_RDLCK:
                    429:                        if ((fp->f_flag & FREAD) == 0) {
                    430:                                error = EBADF;
                    431:                                goto out;
                    432:                        }
                    433:                        atomic_setbits_int(&p->p_flag, P_ADVLOCK);
                    434:                        error = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
                    435:                        goto out;
                    436:
                    437:                case F_WRLCK:
                    438:                        if ((fp->f_flag & FWRITE) == 0) {
                    439:                                error = EBADF;
                    440:                                goto out;
                    441:                        }
                    442:                        atomic_setbits_int(&p->p_flag, P_ADVLOCK);
                    443:                        error = (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
                    444:                        goto out;
                    445:
                    446:                case F_UNLCK:
                    447:                        error = (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
                    448:                                F_POSIX));
                    449:                        goto out;
                    450:
                    451:                default:
                    452:                        error = EINVAL;
                    453:                        goto out;
                    454:                }
                    455:
                    456:        case F_GETLK:
                    457:                if (fp->f_type != DTYPE_VNODE) {
                    458:                        error = EBADF;
                    459:                        break;
                    460:                }
                    461:                vp = (struct vnode *)fp->f_data;
                    462:                /* Copy in the lock structure */
                    463:                error = copyin((caddr_t)SCARG(uap, arg), (caddr_t)&fl,
                    464:                    sizeof (fl));
                    465:                if (error)
                    466:                        break;
                    467:                if (fl.l_whence == SEEK_CUR) {
                    468:                        if (fl.l_start == 0 && fl.l_len < 0) {
                    469:                                /* lockf(3) compliance hack */
                    470:                                fl.l_len = -fl.l_len;
                    471:                                fl.l_start = fp->f_offset - fl.l_len;
                    472:                        } else
                    473:                                fl.l_start += fp->f_offset;
                    474:                }
                    475:                if (fl.l_type != F_RDLCK &&
                    476:                    fl.l_type != F_WRLCK &&
                    477:                    fl.l_type != F_UNLCK &&
                    478:                    fl.l_type != 0) {
                    479:                        error = EINVAL;
                    480:                        break;
                    481:                }
                    482:                error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX);
                    483:                if (error)
                    484:                        break;
                    485:                error = (copyout((caddr_t)&fl, (caddr_t)SCARG(uap, arg),
                    486:                    sizeof (fl)));
                    487:                break;
                    488:
                    489:        default:
                    490:                error = EINVAL;
                    491:                break;
                    492:        }
                    493: out:
                    494:        FRELE(fp);
                    495:        return (error);
                    496: }
                    497:
                    498: /*
                    499:  * Common code for dup, dup2, and fcntl(F_DUPFD).
                    500:  */
                    501: int
                    502: finishdup(struct proc *p, struct file *fp, int old, int new, register_t *retval)
                    503: {
                    504:        struct file *oldfp;
                    505:        struct filedesc *fdp = p->p_fd;
                    506:
                    507:        if (fp->f_count == LONG_MAX-2) {
                    508:                FRELE(fp);
                    509:                return (EDEADLK);
                    510:        }
                    511:
                    512:        /*
                    513:         * Don't fd_getfile here. We want to closef LARVAL files and
                    514:         * closef can deal with that.
                    515:         */
                    516:        oldfp = fdp->fd_ofiles[new];
                    517:        if (oldfp != NULL)
                    518:                FREF(oldfp);
                    519:
                    520:        fdp->fd_ofiles[new] = fp;
                    521:        fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE;
                    522:        fp->f_count++;
                    523:        FRELE(fp);
                    524:        if (oldfp == NULL)
                    525:                fd_used(fdp, new);
                    526:        *retval = new;
                    527:
                    528:        if (oldfp != NULL) {
                    529:                if (new < fdp->fd_knlistsize)
                    530:                        knote_fdclose(p, new);
                    531:                closef(oldfp, p);
                    532:        }
                    533:
                    534:        return (0);
                    535: }
                    536:
                    537: void
                    538: fdremove(struct filedesc *fdp, int fd)
                    539: {
                    540:        fdp->fd_ofiles[fd] = NULL;
                    541:        fd_unused(fdp, fd);
                    542: }
                    543:
                    544: int
                    545: fdrelease(struct proc *p, int fd)
                    546: {
                    547:        struct filedesc *fdp = p->p_fd;
                    548:        struct file **fpp, *fp;
                    549:
                    550:        /*
                    551:         * Don't fd_getfile here. We want to closef LARVAL files and closef
                    552:         * can deal with that.
                    553:         */
                    554:        fpp = &fdp->fd_ofiles[fd];
                    555:        fp = *fpp;
                    556:        if (fp == NULL)
                    557:                return (EBADF);
                    558:        FREF(fp);
                    559:        *fpp = NULL;
                    560:        fdp->fd_ofileflags[fd] = 0;
                    561:        fd_unused(fdp, fd);
                    562:        if (fd < fdp->fd_knlistsize)
                    563:                knote_fdclose(p, fd);
                    564:        return (closef(fp, p));
                    565: }
                    566:
                    567: /*
                    568:  * Close a file descriptor.
                    569:  */
                    570: /* ARGSUSED */
                    571: int
                    572: sys_close(struct proc *p, void *v, register_t *retval)
                    573: {
                    574:        struct sys_close_args /* {
                    575:                syscallarg(int) fd;
                    576:        } */ *uap = v;
                    577:        int fd = SCARG(uap, fd), error;
                    578:        struct filedesc *fdp = p->p_fd;
                    579:
                    580:        if (fd_getfile(fdp, fd) == NULL)
                    581:                return (EBADF);
                    582:        fdplock(fdp);
                    583:        error = fdrelease(p, fd);
                    584:        fdpunlock(fdp);
                    585:
                    586:        return (error);
                    587: }
                    588:
                    589: /*
                    590:  * Return status information about a file descriptor.
                    591:  */
                    592: /* ARGSUSED */
                    593: int
                    594: sys_fstat(struct proc *p, void *v, register_t *retval)
                    595: {
                    596:        struct sys_fstat_args /* {
                    597:                syscallarg(int) fd;
                    598:                syscallarg(struct stat *) sb;
                    599:        } */ *uap = v;
                    600:        int fd = SCARG(uap, fd);
                    601:        struct filedesc *fdp = p->p_fd;
                    602:        struct file *fp;
                    603:        struct stat ub;
                    604:        int error;
                    605:
                    606:        if ((fp = fd_getfile(fdp, fd)) == NULL)
                    607:                return (EBADF);
                    608:        FREF(fp);
                    609:        error = (*fp->f_ops->fo_stat)(fp, &ub, p);
                    610:        FRELE(fp);
                    611:        if (error == 0) {
                    612:                /*
                    613:                 * Don't let non-root see generation numbers
                    614:                 * (for NFS security)
                    615:                 */
                    616:                if (suser(p, 0))
                    617:                        ub.st_gen = 0;
                    618:                error = copyout((caddr_t)&ub, (caddr_t)SCARG(uap, sb),
                    619:                    sizeof (ub));
                    620:        }
                    621:        return (error);
                    622: }
                    623:
                    624: /*
                    625:  * Return pathconf information about a file descriptor.
                    626:  */
                    627: /* ARGSUSED */
                    628: int
                    629: sys_fpathconf(struct proc *p, void *v, register_t *retval)
                    630: {
                    631:        struct sys_fpathconf_args /* {
                    632:                syscallarg(int) fd;
                    633:                syscallarg(int) name;
                    634:        } */ *uap = v;
                    635:        int fd = SCARG(uap, fd);
                    636:        struct filedesc *fdp = p->p_fd;
                    637:        struct file *fp;
                    638:        struct vnode *vp;
                    639:        int error;
                    640:
                    641:        if ((fp = fd_getfile(fdp, fd)) == NULL)
                    642:                return (EBADF);
                    643:        FREF(fp);
                    644:        switch (fp->f_type) {
                    645:        case DTYPE_PIPE:
                    646:        case DTYPE_SOCKET:
                    647:                if (SCARG(uap, name) != _PC_PIPE_BUF) {
                    648:                        error = EINVAL;
                    649:                        break;
                    650:                }
                    651:                *retval = PIPE_BUF;
                    652:                error = 0;
                    653:                break;
                    654:
                    655:        case DTYPE_VNODE:
                    656:                vp = (struct vnode *)fp->f_data;
                    657:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
                    658:                error = VOP_PATHCONF(vp, SCARG(uap, name), retval);
                    659:                VOP_UNLOCK(vp, 0, p);
                    660:                break;
                    661:
                    662:        default:
                    663:                error = EOPNOTSUPP;
                    664:                break;
                    665:        }
                    666:        FRELE(fp);
                    667:        return (error);
                    668: }
                    669:
                    670: /*
                    671:  * Allocate a file descriptor for the process.
                    672:  */
                    673: int
                    674: fdalloc(struct proc *p, int want, int *result)
                    675: {
                    676:        struct filedesc *fdp = p->p_fd;
                    677:        int lim, last, i;
                    678:        u_int new, off;
                    679:
                    680:        /*
                    681:         * Search for a free descriptor starting at the higher
                    682:         * of want or fd_freefile.  If that fails, consider
                    683:         * expanding the ofile array.
                    684:         */
                    685: restart:
                    686:        lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
                    687:        last = min(fdp->fd_nfiles, lim);
                    688:        if ((i = want) < fdp->fd_freefile)
                    689:                i = fdp->fd_freefile;
                    690:        off = i >> NDENTRYSHIFT;
                    691:        new = find_next_zero(fdp->fd_himap, off,
                    692:            (last + NDENTRIES - 1) >> NDENTRYSHIFT);
                    693:        if (new != -1) {
                    694:                i = find_next_zero(&fdp->fd_lomap[new],
                    695:                                   new > off ? 0 : i & NDENTRYMASK,
                    696:                                   NDENTRIES);
                    697:                if (i == -1) {
                    698:                        /*
                    699:                         * Free file descriptor in this block was
                    700:                         * below want, try again with higher want.
                    701:                         */
                    702:                        want = (new + 1) << NDENTRYSHIFT;
                    703:                        goto restart;
                    704:                }
                    705:                i += (new << NDENTRYSHIFT);
                    706:                if (i < last) {
                    707:                        fd_used(fdp, i);
                    708:                        if (want <= fdp->fd_freefile)
                    709:                                fdp->fd_freefile = i;
                    710:                        *result = i;
                    711:                        return (0);
                    712:                }
                    713:        }
                    714:        if (fdp->fd_nfiles >= lim)
                    715:                return (EMFILE);
                    716:
                    717:        return (ENOSPC);
                    718: }
                    719:
                    720: void
                    721: fdexpand(struct proc *p)
                    722: {
                    723:        struct filedesc *fdp = p->p_fd;
                    724:        int nfiles, i;
                    725:        struct file **newofile;
                    726:        char *newofileflags;
                    727:        u_int *newhimap, *newlomap;
                    728:
                    729:        /*
                    730:         * No space in current array.
                    731:         */
                    732:        if (fdp->fd_nfiles < NDEXTENT)
                    733:                nfiles = NDEXTENT;
                    734:        else
                    735:                nfiles = 2 * fdp->fd_nfiles;
                    736:
                    737:        newofile = malloc(nfiles * OFILESIZE, M_FILEDESC, M_WAITOK);
                    738:        newofileflags = (char *) &newofile[nfiles];
                    739:
                    740:        /*
                    741:         * Copy the existing ofile and ofileflags arrays
                    742:         * and zero the new portion of each array.
                    743:         */
                    744:        bcopy(fdp->fd_ofiles, newofile,
                    745:                (i = sizeof(struct file *) * fdp->fd_nfiles));
                    746:        bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
                    747:        bcopy(fdp->fd_ofileflags, newofileflags,
                    748:                (i = sizeof(char) * fdp->fd_nfiles));
                    749:        bzero(newofileflags + i, nfiles * sizeof(char) - i);
                    750:
                    751:        if (fdp->fd_nfiles > NDFILE)
                    752:                free(fdp->fd_ofiles, M_FILEDESC);
                    753:
                    754:        if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) {
                    755:                newhimap = malloc(NDHISLOTS(nfiles) * sizeof(u_int),
                    756:                    M_FILEDESC, M_WAITOK);
                    757:                newlomap = malloc(NDLOSLOTS(nfiles) * sizeof(u_int),
                    758:                    M_FILEDESC, M_WAITOK);
                    759:
                    760:                bcopy(fdp->fd_himap, newhimap,
                    761:                    (i = NDHISLOTS(fdp->fd_nfiles) * sizeof(u_int)));
                    762:                bzero((char *)newhimap + i,
                    763:                    NDHISLOTS(nfiles) * sizeof(u_int) - i);
                    764:
                    765:                bcopy(fdp->fd_lomap, newlomap,
                    766:                    (i = NDLOSLOTS(fdp->fd_nfiles) * sizeof(u_int)));
                    767:                bzero((char *)newlomap + i,
                    768:                    NDLOSLOTS(nfiles) * sizeof(u_int) - i);
                    769:
                    770:                if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
                    771:                        free(fdp->fd_himap, M_FILEDESC);
                    772:                        free(fdp->fd_lomap, M_FILEDESC);
                    773:                }
                    774:                fdp->fd_himap = newhimap;
                    775:                fdp->fd_lomap = newlomap;
                    776:        }
                    777:        fdp->fd_ofiles = newofile;
                    778:        fdp->fd_ofileflags = newofileflags;
                    779:        fdp->fd_nfiles = nfiles;
                    780: }
                    781:
                    782: /*
                    783:  * Create a new open file structure and allocate
                    784:  * a file descriptor for the process that refers to it.
                    785:  */
                    786: int
                    787: falloc(struct proc *p, struct file **resultfp, int *resultfd)
                    788: {
                    789:        struct file *fp, *fq;
                    790:        int error, i;
                    791:
                    792: restart:
                    793:        if ((error = fdalloc(p, 0, &i)) != 0) {
                    794:                if (error == ENOSPC) {
                    795:                        fdexpand(p);
                    796:                        goto restart;
                    797:                }
                    798:                return (error);
                    799:        }
                    800:        if (nfiles >= maxfiles) {
                    801:                fd_unused(p->p_fd, i);
                    802:                tablefull("file");
                    803:                return (ENFILE);
                    804:        }
                    805:        /*
                    806:         * Allocate a new file descriptor.
                    807:         * If the process has file descriptor zero open, add to the list
                    808:         * of open files at that point, otherwise put it at the front of
                    809:         * the list of open files.
                    810:         */
                    811:        nfiles++;
                    812:        fp = pool_get(&file_pool, PR_WAITOK);
                    813:        bzero(fp, sizeof(struct file));
                    814:        fp->f_iflags = FIF_LARVAL;
                    815:        if ((fq = p->p_fd->fd_ofiles[0]) != NULL) {
                    816:                LIST_INSERT_AFTER(fq, fp, f_list);
                    817:        } else {
                    818:                LIST_INSERT_HEAD(&filehead, fp, f_list);
                    819:        }
                    820:        p->p_fd->fd_ofiles[i] = fp;
                    821:        fp->f_count = 1;
                    822:        fp->f_cred = p->p_ucred;
                    823:        crhold(fp->f_cred);
                    824:        if (resultfp)
                    825:                *resultfp = fp;
                    826:        if (resultfd)
                    827:                *resultfd = i;
                    828:        FREF(fp);
                    829:        return (0);
                    830: }
                    831:
                    832: /*
                    833:  * Build a new filedesc structure.
                    834:  */
                    835: struct filedesc *
                    836: fdinit(struct proc *p)
                    837: {
                    838:        struct filedesc0 *newfdp;
                    839:        extern int cmask;
                    840:
                    841:        newfdp = pool_get(&fdesc_pool, PR_WAITOK);
                    842:        bzero(newfdp, sizeof(struct filedesc0));
                    843:        if (p != NULL) {
                    844:                struct filedesc *fdp = p->p_fd;
                    845:
                    846:                newfdp->fd_fd.fd_cdir = fdp->fd_cdir;
                    847:                VREF(newfdp->fd_fd.fd_cdir);
                    848:                newfdp->fd_fd.fd_rdir = fdp->fd_rdir;
                    849:                if (newfdp->fd_fd.fd_rdir)
                    850:                        VREF(newfdp->fd_fd.fd_rdir);
                    851:        }
                    852:        rw_init(&newfdp->fd_fd.fd_lock, "fdlock");
                    853:
                    854:        /* Create the file descriptor table. */
                    855:        newfdp->fd_fd.fd_refcnt = 1;
                    856:        newfdp->fd_fd.fd_cmask = cmask;
                    857:        newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
                    858:        newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
                    859:        newfdp->fd_fd.fd_nfiles = NDFILE;
                    860:        newfdp->fd_fd.fd_himap = newfdp->fd_dhimap;
                    861:        newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap;
                    862:        newfdp->fd_fd.fd_knlistsize = -1;
                    863:
                    864:        newfdp->fd_fd.fd_freefile = 0;
                    865:        newfdp->fd_fd.fd_lastfile = 0;
                    866:
                    867:        return (&newfdp->fd_fd);
                    868: }
                    869:
                    870: /*
                    871:  * Share a filedesc structure.
                    872:  */
                    873: struct filedesc *
                    874: fdshare(struct proc *p)
                    875: {
                    876:        p->p_fd->fd_refcnt++;
                    877:        return (p->p_fd);
                    878: }
                    879:
                    880: /*
                    881:  * Copy a filedesc structure.
                    882:  */
                    883: struct filedesc *
                    884: fdcopy(struct proc *p)
                    885: {
                    886:        struct filedesc *newfdp, *fdp = p->p_fd;
                    887:        struct file **fpp;
                    888:        int i;
                    889:
                    890:        newfdp = pool_get(&fdesc_pool, PR_WAITOK);
                    891:        bcopy(fdp, newfdp, sizeof(struct filedesc));
                    892:        if (newfdp->fd_cdir)
                    893:                VREF(newfdp->fd_cdir);
                    894:        if (newfdp->fd_rdir)
                    895:                VREF(newfdp->fd_rdir);
                    896:        newfdp->fd_refcnt = 1;
                    897:
                    898:        /*
                    899:         * If the number of open files fits in the internal arrays
                    900:         * of the open file structure, use them, otherwise allocate
                    901:         * additional memory for the number of descriptors currently
                    902:         * in use.
                    903:         */
                    904:        if (newfdp->fd_lastfile < NDFILE) {
                    905:                newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
                    906:                newfdp->fd_ofileflags =
                    907:                    ((struct filedesc0 *) newfdp)->fd_dfileflags;
                    908:                i = NDFILE;
                    909:        } else {
                    910:                /*
                    911:                 * Compute the smallest multiple of NDEXTENT needed
                    912:                 * for the file descriptors currently in use,
                    913:                 * allowing the table to shrink.
                    914:                 */
                    915:                i = newfdp->fd_nfiles;
                    916:                while (i >= 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
                    917:                        i /= 2;
                    918:                newfdp->fd_ofiles = malloc(i * OFILESIZE, M_FILEDESC, M_WAITOK);
                    919:                newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
                    920:        }
                    921:        if (NDHISLOTS(i) <= NDHISLOTS(NDFILE)) {
                    922:                newfdp->fd_himap =
                    923:                        ((struct filedesc0 *) newfdp)->fd_dhimap;
                    924:                newfdp->fd_lomap =
                    925:                        ((struct filedesc0 *) newfdp)->fd_dlomap;
                    926:        } else {
                    927:                newfdp->fd_himap = malloc(NDHISLOTS(i) * sizeof(u_int),
                    928:                    M_FILEDESC, M_WAITOK);
                    929:                newfdp->fd_lomap = malloc(NDLOSLOTS(i) * sizeof(u_int),
                    930:                    M_FILEDESC, M_WAITOK);
                    931:        }
                    932:        newfdp->fd_nfiles = i;
                    933:        bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
                    934:        bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
                    935:        bcopy(fdp->fd_himap, newfdp->fd_himap, NDHISLOTS(i) * sizeof(u_int));
                    936:        bcopy(fdp->fd_lomap, newfdp->fd_lomap, NDLOSLOTS(i) * sizeof(u_int));
                    937:
                    938:        /*
                    939:         * kq descriptors cannot be copied.
                    940:         */
                    941:        if (newfdp->fd_knlistsize != -1) {
                    942:                fpp = newfdp->fd_ofiles;
                    943:                for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++)
                    944:                        if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE)
                    945:                                fdremove(newfdp, i);
                    946:                newfdp->fd_knlist = NULL;
                    947:                newfdp->fd_knlistsize = -1;
                    948:                newfdp->fd_knhash = NULL;
                    949:                newfdp->fd_knhashmask = 0;
                    950:        }
                    951:
                    952:        fpp = newfdp->fd_ofiles;
                    953:        for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++)
                    954:                if (*fpp != NULL) {
                    955:                        /*
                    956:                         * XXX Gruesome hack. If count gets too high, fail
                    957:                         * to copy an fd, since fdcopy()'s callers do not
                    958:                         * permit it to indicate failure yet.
                    959:                         */
                    960:                        if ((*fpp)->f_count == LONG_MAX-2)
                    961:                                fdremove(newfdp, i);
                    962:                        else
                    963:                                (*fpp)->f_count++;
                    964:                }
                    965:        return (newfdp);
                    966: }
                    967:
                    968: /*
                    969:  * Release a filedesc structure.
                    970:  */
                    971: void
                    972: fdfree(struct proc *p)
                    973: {
                    974:        struct filedesc *fdp = p->p_fd;
                    975:        struct file **fpp, *fp;
                    976:        int i;
                    977:
                    978:        if (--fdp->fd_refcnt > 0)
                    979:                return;
                    980:        fpp = fdp->fd_ofiles;
                    981:        for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) {
                    982:                fp = *fpp;
                    983:                if (fp != NULL) {
                    984:                        FREF(fp);
                    985:                        *fpp = NULL;
                    986:                        (void) closef(fp, p);
                    987:                }
                    988:        }
                    989:        p->p_fd = NULL;
                    990:        if (fdp->fd_nfiles > NDFILE)
                    991:                free(fdp->fd_ofiles, M_FILEDESC);
                    992:        if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
                    993:                free(fdp->fd_himap, M_FILEDESC);
                    994:                free(fdp->fd_lomap, M_FILEDESC);
                    995:        }
                    996:        if (fdp->fd_cdir)
                    997:                vrele(fdp->fd_cdir);
                    998:        if (fdp->fd_rdir)
                    999:                vrele(fdp->fd_rdir);
                   1000:        if (fdp->fd_knlist)
                   1001:                FREE(fdp->fd_knlist, M_TEMP);
                   1002:        if (fdp->fd_knhash)
                   1003:                FREE(fdp->fd_knhash, M_TEMP);
                   1004:        pool_put(&fdesc_pool, fdp);
                   1005: }
                   1006:
                   1007: /*
                   1008:  * Internal form of close.
                   1009:  * Decrement reference count on file structure.
                   1010:  * Note: p may be NULL when closing a file
                   1011:  * that was being passed in a message.
                   1012:  *
                   1013:  * The fp must have its usecount bumped and will be FRELEd here.
                   1014:  */
                   1015: int
                   1016: closef(struct file *fp, struct proc *p)
                   1017: {
                   1018:        struct vnode *vp;
                   1019:        struct flock lf;
                   1020:        int error;
                   1021:
                   1022:        if (fp == NULL)
                   1023:                return (0);
                   1024:
                   1025:        /*
                   1026:         * POSIX record locking dictates that any close releases ALL
                   1027:         * locks owned by this process.  This is handled by setting
                   1028:         * a flag in the unlock to free ONLY locks obeying POSIX
                   1029:         * semantics, and not to free BSD-style file locks.
                   1030:         * If the descriptor was in a message, POSIX-style locks
                   1031:         * aren't passed with the descriptor.
                   1032:         */
                   1033:        if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
                   1034:                lf.l_whence = SEEK_SET;
                   1035:                lf.l_start = 0;
                   1036:                lf.l_len = 0;
                   1037:                lf.l_type = F_UNLCK;
                   1038:                vp = (struct vnode *)fp->f_data;
                   1039:                (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
                   1040:        }
                   1041:
                   1042:        /*
                   1043:         * Some files passed to this function could be accessed
                   1044:         * without a FILE_IS_USABLE check (and in some cases it's perfectly
                   1045:         * legal), we must beware of files where someone already won the
                   1046:         * race to FIF_WANTCLOSE.
                   1047:         */
                   1048:        if ((fp->f_iflags & FIF_WANTCLOSE) != 0) {
                   1049:                FRELE(fp);
                   1050:                return (0);
                   1051:        }
                   1052:
                   1053:        if (--fp->f_count > 0) {
                   1054:                FRELE(fp);
                   1055:                return (0);
                   1056:        }
                   1057:
                   1058: #ifdef DIAGNOSTIC
                   1059:        if (fp->f_count < 0)
                   1060:                panic("closef: count < 0");
                   1061: #endif
                   1062:
                   1063:        /* Wait for the last usecount to drain. */
                   1064:        fp->f_iflags |= FIF_WANTCLOSE;
                   1065:        while (fp->f_usecount > 1)
                   1066:                tsleep(&fp->f_usecount, PRIBIO, "closef", 0);
                   1067:
                   1068:        if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
                   1069:                lf.l_whence = SEEK_SET;
                   1070:                lf.l_start = 0;
                   1071:                lf.l_len = 0;
                   1072:                lf.l_type = F_UNLCK;
                   1073:                vp = (struct vnode *)fp->f_data;
                   1074:                (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
                   1075:        }
                   1076:        if (fp->f_ops)
                   1077:                error = (*fp->f_ops->fo_close)(fp, p);
                   1078:        else
                   1079:                error = 0;
                   1080:
                   1081:        /* Free fp */
                   1082:        LIST_REMOVE(fp, f_list);
                   1083:        crfree(fp->f_cred);
                   1084: #ifdef DIAGNOSTIC
                   1085:        if (fp->f_count != 0 || fp->f_usecount != 1)
                   1086:                panic("closef: count: %d/%d", fp->f_count, fp->f_usecount);
                   1087: #endif
                   1088:        nfiles--;
                   1089:        pool_put(&file_pool, fp);
                   1090:
                   1091:        return (error);
                   1092: }
                   1093:
                   1094: /*
                   1095:  * Apply an advisory lock on a file descriptor.
                   1096:  *
                   1097:  * Just attempt to get a record lock of the requested type on
                   1098:  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
                   1099:  */
                   1100: /* ARGSUSED */
                   1101: int
                   1102: sys_flock(struct proc *p, void *v, register_t *retval)
                   1103: {
                   1104:        struct sys_flock_args /* {
                   1105:                syscallarg(int) fd;
                   1106:                syscallarg(int) how;
                   1107:        } */ *uap = v;
                   1108:        int fd = SCARG(uap, fd);
                   1109:        int how = SCARG(uap, how);
                   1110:        struct filedesc *fdp = p->p_fd;
                   1111:        struct file *fp;
                   1112:        struct vnode *vp;
                   1113:        struct flock lf;
                   1114:        int error;
                   1115:
                   1116:        if ((fp = fd_getfile(fdp, fd)) == NULL)
                   1117:                return (EBADF);
                   1118:        if (fp->f_type != DTYPE_VNODE)
                   1119:                return (EOPNOTSUPP);
                   1120:        vp = (struct vnode *)fp->f_data;
                   1121:        lf.l_whence = SEEK_SET;
                   1122:        lf.l_start = 0;
                   1123:        lf.l_len = 0;
                   1124:        if (how & LOCK_UN) {
                   1125:                lf.l_type = F_UNLCK;
                   1126:                fp->f_flag &= ~FHASLOCK;
                   1127:                error = VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
                   1128:                goto out;
                   1129:        }
                   1130:        if (how & LOCK_EX)
                   1131:                lf.l_type = F_WRLCK;
                   1132:        else if (how & LOCK_SH)
                   1133:                lf.l_type = F_RDLCK;
                   1134:        else {
                   1135:                error = EINVAL;
                   1136:                goto out;
                   1137:        }
                   1138:        fp->f_flag |= FHASLOCK;
                   1139:        if (how & LOCK_NB)
                   1140:                error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK);
                   1141:        else
                   1142:                error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT);
                   1143: out:
                   1144:        return (error);
                   1145: }
                   1146:
                   1147: /*
                   1148:  * File Descriptor pseudo-device driver (/dev/fd/).
                   1149:  *
                   1150:  * Opening minor device N dup()s the file (if any) connected to file
                   1151:  * descriptor N belonging to the calling process.  Note that this driver
                   1152:  * consists of only the ``open()'' routine, because all subsequent
                   1153:  * references to this file will be direct to the other driver.
                   1154:  */
                   1155: /* ARGSUSED */
                   1156: int
                   1157: filedescopen(dev_t dev, int mode, int type, struct proc *p)
                   1158: {
                   1159:
                   1160:        /*
                   1161:         * XXX Kludge: set curproc->p_dupfd to contain the value of the
                   1162:         * the file descriptor being sought for duplication. The error
                   1163:         * return ensures that the vnode for this device will be released
                   1164:         * by vn_open. Open will detect this special error and take the
                   1165:         * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
                   1166:         * will simply report the error.
                   1167:         */
                   1168:        p->p_dupfd = minor(dev);
                   1169:        return (ENODEV);
                   1170: }
                   1171:
                   1172: /*
                   1173:  * Duplicate the specified descriptor to a free descriptor.
                   1174:  */
                   1175: int
                   1176: dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode, int error)
                   1177: {
                   1178:        struct file *wfp;
                   1179:
                   1180:        /*
                   1181:         * Assume that the filename was user-specified; applications do
                   1182:         * not tend to open /dev/fd/# when they can just call dup()
                   1183:         */
                   1184:        if ((curproc->p_flag & (P_SUGIDEXEC | P_SUGID))) {
                   1185:                if (curproc->p_descfd == 255)
                   1186:                        return (EPERM);
                   1187:                if (curproc->p_descfd != curproc->p_dupfd)
                   1188:                        return (EPERM);
                   1189:        }
                   1190:
                   1191:        /*
                   1192:         * If the to-be-dup'd fd number is greater than the allowed number
                   1193:         * of file descriptors, or the fd to be dup'd has already been
                   1194:         * closed, reject. Note, there is no need to check for new == old
                   1195:         * because fd_getfile will return NULL if the file at indx is
                   1196:         * newly created by falloc (FIF_LARVAL).
                   1197:         */
                   1198:        if ((wfp = fd_getfile(fdp, dfd)) == NULL)
                   1199:                return (EBADF);
                   1200:
                   1201:        /*
                   1202:         * There are two cases of interest here.
                   1203:         *
                   1204:         * For ENODEV simply dup (dfd) to file descriptor
                   1205:         * (indx) and return.
                   1206:         *
                   1207:         * For ENXIO steal away the file structure from (dfd) and
                   1208:         * store it in (indx).  (dfd) is effectively closed by
                   1209:         * this operation.
                   1210:         *
                   1211:         * Any other error code is just returned.
                   1212:         */
                   1213:        switch (error) {
                   1214:        case ENODEV:
                   1215:                /*
                   1216:                 * Check that the mode the file is being opened for is a
                   1217:                 * subset of the mode of the existing descriptor.
                   1218:                 */
                   1219:                if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
                   1220:                        return (EACCES);
                   1221:                if (wfp->f_count == LONG_MAX-2)
                   1222:                        return (EDEADLK);
                   1223:                fdp->fd_ofiles[indx] = wfp;
                   1224:                fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
                   1225:                wfp->f_count++;
                   1226:                fd_used(fdp, indx);
                   1227:                return (0);
                   1228:
                   1229:        case ENXIO:
                   1230:                /*
                   1231:                 * Steal away the file pointer from dfd, and stuff it into indx.
                   1232:                 */
                   1233:                fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
                   1234:                fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
                   1235:                fdp->fd_ofiles[dfd] = NULL;
                   1236:                fdp->fd_ofileflags[dfd] = 0;
                   1237:                /*
                   1238:                 * Complete the clean up of the filedesc structure by
                   1239:                 * recomputing the various hints.
                   1240:                 */
                   1241:                fd_used(fdp, indx);
                   1242:                fd_unused(fdp, dfd);
                   1243:                return (0);
                   1244:
                   1245:        default:
                   1246:                return (error);
                   1247:        }
                   1248:        /* NOTREACHED */
                   1249: }
                   1250:
                   1251: /*
                   1252:  * Close any files on exec?
                   1253:  */
                   1254: void
                   1255: fdcloseexec(struct proc *p)
                   1256: {
                   1257:        struct filedesc *fdp = p->p_fd;
                   1258:        int fd;
                   1259:
                   1260:        for (fd = 0; fd <= fdp->fd_lastfile; fd++)
                   1261:                if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
                   1262:                        (void) fdrelease(p, fd);
                   1263: }
                   1264:
                   1265: int
                   1266: sys_closefrom(struct proc *p, void *v, register_t *retval)
                   1267: {
                   1268:        struct sys_closefrom_args *uap = v;
                   1269:        struct filedesc *fdp = p->p_fd;
                   1270:        u_int startfd, i;
                   1271:
                   1272:        startfd = SCARG(uap, fd);
                   1273:        fdplock(fdp);
                   1274:
                   1275:        if (startfd > fdp->fd_lastfile) {
                   1276:                fdpunlock(fdp);
                   1277:                return (EBADF);
                   1278:        }
                   1279:
                   1280:        for (i = startfd; i <= fdp->fd_lastfile; i++)
                   1281:                fdrelease(p, i);
                   1282:
                   1283:        fdpunlock(fdp);
                   1284:        return (0);
                   1285: }

CVSweb