[BACK]Return to kern_descrip.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/kern_descrip.c, Revision 1.124

1.124   ! yamt        1: /*     $NetBSD: kern_descrip.c,v 1.123 2004/01/07 09:26:29 jdolecek Exp $      */
1.22      cgd         2:
1.16      cgd         3: /*
1.17      cgd         4:  * Copyright (c) 1982, 1986, 1989, 1991, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
1.16      cgd         6:  * (c) UNIX System Laboratories, Inc.
                      7:  * All or some portions of this file are derived from material licensed
                      8:  * to the University of California by American Telephone and Telegraph
                      9:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     10:  * the permission of UNIX System Laboratories, Inc.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
1.111     agc        20:  * 3. Neither the name of the University nor the names of its contributors
1.16      cgd        21:  *    may be used to endorse or promote products derived from this software
                     22:  *    without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     34:  * SUCH DAMAGE.
                     35:  *
1.51      fvdl       36:  *     @(#)kern_descrip.c      8.8 (Berkeley) 2/14/95
1.16      cgd        37:  */
1.81      lukem      38:
                     39: #include <sys/cdefs.h>
1.124   ! yamt       40: __KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.123 2004/01/07 09:26:29 jdolecek Exp $");
1.50      mrg        41:
1.16      cgd        42: #include <sys/param.h>
                     43: #include <sys/systm.h>
                     44: #include <sys/filedesc.h>
                     45: #include <sys/kernel.h>
                     46: #include <sys/vnode.h>
                     47: #include <sys/proc.h>
                     48: #include <sys/file.h>
1.86      christos   49: #include <sys/namei.h>
1.16      cgd        50: #include <sys/socket.h>
                     51: #include <sys/socketvar.h>
                     52: #include <sys/stat.h>
                     53: #include <sys/ioctl.h>
                     54: #include <sys/fcntl.h>
                     55: #include <sys/malloc.h>
1.55      thorpej    56: #include <sys/pool.h>
1.16      cgd        57: #include <sys/syslog.h>
1.17      cgd        58: #include <sys/unistd.h>
1.16      cgd        59: #include <sys/resourcevar.h>
1.42      christos   60: #include <sys/conf.h>
1.96      jdolecek   61: #include <sys/event.h>
1.16      cgd        62:
1.25      cgd        63: #include <sys/mount.h>
1.99      thorpej    64: #include <sys/sa.h>
1.25      cgd        65: #include <sys/syscallargs.h>
1.38      christos   66:
1.16      cgd        67: /*
                     68:  * Descriptor management.
                     69:  */
1.72      lukem      70: struct filelist        filehead;       /* head of list of open files */
                     71: int            nfiles;         /* actual number of open files */
                     72: struct pool    file_pool;      /* memory pool for file structures */
                     73: struct pool    cwdi_pool;      /* memory pool for cwdinfo structures */
                     74: struct pool    filedesc0_pool; /* memory pool for filedesc0 structures */
1.101     thorpej    75:
1.102     pk         76: /* Global file list lock */
                     77: static struct simplelock filelist_slock = SIMPLELOCK_INITIALIZER;
                     78:
1.101     thorpej    79: MALLOC_DEFINE(M_FILE, "file", "Open file structure");
                     80: MALLOC_DEFINE(M_FILEDESC, "file desc", "Open file descriptor table");
                     81: MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer");
1.72      lukem      82:
                     83: static __inline void   fd_used(struct filedesc *, int);
                     84: static __inline void   fd_unused(struct filedesc *, int);
1.115     provos     85: static __inline int    find_next_zero(uint32_t *, int, u_int);
1.110     fvdl       86: int                    finishdup(struct proc *, int, int, register_t *);
1.115     provos     87: int                    find_last_set(struct filedesc *, int);
1.110     fvdl       88: int                    fcntl_forfs(int, struct proc *, int, void *);
1.94      gehenna    89:
                     90: dev_type_open(filedescopen);
                     91:
                     92: const struct cdevsw filedesc_cdevsw = {
                     93:        filedescopen, noclose, noread, nowrite, noioctl,
1.96      jdolecek   94:        nostop, notty, nopoll, nommap, nokqfilter,
1.94      gehenna    95: };
1.38      christos   96:
1.115     provos     97: static __inline int
                     98: find_next_zero(uint32_t *bitmap, int want, u_int bits)
                     99: {
                    100:        int i, off, maxoff;
                    101:        uint32_t sub;
                    102:
                    103:        if (want > bits)
                    104:                return -1;
                    105:
                    106:        off = want >> NDENTRYSHIFT;
                    107:        i = want & NDENTRYMASK;
                    108:        if (i) {
                    109:                sub = bitmap[off] | ((u_int)~0 >> (NDENTRIES - i));
                    110:                if (sub != ~0)
                    111:                        goto found;
                    112:                off++;
                    113:        }
                    114:
                    115:        maxoff = NDLOSLOTS(bits);
                    116:        while (off < maxoff) {
                    117:                if ((sub = bitmap[off]) != ~0)
                    118:                        goto found;
                    119:                off++;
                    120:        }
                    121:
                    122:        return (-1);
                    123:
                    124:  found:
                    125:        return (off << NDENTRYSHIFT) + ffs(~sub) - 1;
                    126: }
                    127:
                    128: int
                    129: find_last_set(struct filedesc *fd, int last)
                    130: {
                    131:        int off, i;
                    132:        struct file **ofiles = fd->fd_ofiles;
                    133:        uint32_t *bitmap = fd->fd_lomap;
                    134:
                    135:        off = (last - 1) >> NDENTRYSHIFT;
                    136:
1.121     provos    137:        while (off >= 0 && !bitmap[off])
1.115     provos    138:                off--;
                    139:
                    140:        if (off < 0)
                    141:                return (0);
                    142:
                    143:        i = ((off + 1) << NDENTRYSHIFT) - 1;
                    144:        if (i >= last)
                    145:                i = last - 1;
                    146:
                    147:        while (i > 0 && ofiles[i] == NULL)
                    148:                i--;
                    149:
                    150:        return (i);
                    151: }
                    152:
1.38      christos  153: static __inline void
1.72      lukem     154: fd_used(struct filedesc *fdp, int fd)
1.27      mycroft   155: {
1.115     provos    156:        u_int off = fd >> NDENTRYSHIFT;
                    157:
1.124   ! yamt      158:        KDASSERT((fdp->fd_lomap[off] & (1 << (fd & NDENTRYMASK))) == 0);
        !           159:
1.115     provos    160:        fdp->fd_lomap[off] |= 1 << (fd & NDENTRYMASK);
1.124   ! yamt      161:        if (fdp->fd_lomap[off] == ~0) {
        !           162:                KDASSERT((fdp->fd_himap[off >> NDENTRYSHIFT] &
        !           163:                    (1 << (off & NDENTRYMASK))) == 0);
1.115     provos    164:                fdp->fd_himap[off >> NDENTRYSHIFT] |= 1 << (off & NDENTRYMASK);
1.124   ! yamt      165:        }
1.27      mycroft   166:
                    167:        if (fd > fdp->fd_lastfile)
                    168:                fdp->fd_lastfile = fd;
                    169: }
                    170:
1.38      christos  171: static __inline void
1.72      lukem     172: fd_unused(struct filedesc *fdp, int fd)
1.27      mycroft   173: {
1.115     provos    174:        u_int off = fd >> NDENTRYSHIFT;
1.27      mycroft   175:
                    176:        if (fd < fdp->fd_freefile)
                    177:                fdp->fd_freefile = fd;
1.115     provos    178:
1.124   ! yamt      179:        if (fdp->fd_lomap[off] == ~0) {
        !           180:                KDASSERT((fdp->fd_himap[off >> NDENTRYSHIFT] &
        !           181:                    (1 << (off & NDENTRYMASK))) != 0);
        !           182:                fdp->fd_himap[off >> NDENTRYSHIFT] &=
        !           183:                    ~(1 << (off & NDENTRYMASK));
        !           184:        }
        !           185:        KDASSERT((fdp->fd_lomap[off] & (1 << (fd & NDENTRYMASK))) != 0);
1.115     provos    186:        fdp->fd_lomap[off] &= ~(1 << (fd & NDENTRYMASK));
                    187:
1.27      mycroft   188: #ifdef DIAGNOSTIC
                    189:        if (fd > fdp->fd_lastfile)
                    190:                panic("fd_unused: fd_lastfile inconsistent");
                    191: #endif
1.115     provos    192:        if (fd == fdp->fd_lastfile)
                    193:                fdp->fd_lastfile = find_last_set(fdp, fd);
1.27      mycroft   194: }
                    195:
1.103     pk        196: /*
                    197:  * Lookup the file structure corresponding to a file descriptor
                    198:  * and return it locked.
                    199:  * Note: typical usage is: `fp = fd_getfile(..); FILE_USE(fp);'
                    200:  * The locking strategy has been optimised for this case, i.e.
                    201:  * fd_getfile() returns the file locked while FILE_USE() will increment
                    202:  * the file's use count and unlock.
                    203:  */
1.77      thorpej   204: struct file *
                    205: fd_getfile(struct filedesc *fdp, int fd)
                    206: {
                    207:        struct file *fp;
                    208:
                    209:        if ((u_int) fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL)
                    210:                return (NULL);
                    211:
1.103     pk        212:        simple_lock(&fp->f_slock);
                    213:        if (FILE_IS_USABLE(fp) == 0) {
                    214:                simple_unlock(&fp->f_slock);
1.77      thorpej   215:                return (NULL);
1.103     pk        216:        }
1.77      thorpej   217:
                    218:        return (fp);
                    219: }
                    220:
1.16      cgd       221: /*
                    222:  * System calls on descriptors.
                    223:  */
1.18      cgd       224:
1.16      cgd       225: /*
                    226:  * Duplicate a file descriptor.
                    227:  */
                    228: /* ARGSUSED */
1.38      christos  229: int
1.99      thorpej   230: sys_dup(struct lwp *l, void *v, register_t *retval)
1.36      thorpej   231: {
1.37      mycroft   232:        struct sys_dup_args /* {
1.72      lukem     233:                syscallarg(int) fd;
1.36      thorpej   234:        } */ *uap = v;
1.72      lukem     235:        struct file     *fp;
                    236:        struct filedesc *fdp;
1.99      thorpej   237:        struct proc     *p;
1.72      lukem     238:        int             old, new, error;
                    239:
1.99      thorpej   240:        p = l->l_proc;
1.72      lukem     241:        fdp = p->p_fd;
                    242:        old = SCARG(uap, fd);
1.16      cgd       243:
1.75      thorpej   244:  restart:
1.77      thorpej   245:        if ((fp = fd_getfile(fdp, old)) == NULL)
1.16      cgd       246:                return (EBADF);
1.59      thorpej   247:
                    248:        FILE_USE(fp);
                    249:
                    250:        if ((error = fdalloc(p, 0, &new)) != 0) {
1.76      thorpej   251:                if (error == ENOSPC) {
                    252:                        fdexpand(p);
1.110     fvdl      253:                        FILE_UNUSE(fp, p);
1.76      thorpej   254:                        goto restart;
                    255:                }
1.110     fvdl      256:                FILE_UNUSE(fp, p);
1.16      cgd       257:                return (error);
1.59      thorpej   258:        }
                    259:
                    260:        /* finishdup() will unuse the descriptors for us */
1.110     fvdl      261:        return (finishdup(p, old, new, retval));
1.16      cgd       262: }
                    263:
                    264: /*
                    265:  * Duplicate a file descriptor to a particular value.
                    266:  */
                    267: /* ARGSUSED */
1.38      christos  268: int
1.99      thorpej   269: sys_dup2(struct lwp *l, void *v, register_t *retval)
1.36      thorpej   270: {
1.37      mycroft   271:        struct sys_dup2_args /* {
1.72      lukem     272:                syscallarg(int) from;
                    273:                syscallarg(int) to;
1.36      thorpej   274:        } */ *uap = v;
1.72      lukem     275:        struct file     *fp;
                    276:        struct filedesc *fdp;
1.99      thorpej   277:        struct proc     *p;
1.72      lukem     278:        int             old, new, i, error;
                    279:
1.99      thorpej   280:        p = l->l_proc;
1.72      lukem     281:        fdp = p->p_fd;
                    282:        old = SCARG(uap, from);
                    283:        new = SCARG(uap, to);
1.16      cgd       284:
1.75      thorpej   285:  restart:
1.77      thorpej   286:        if ((fp = fd_getfile(fdp, old)) == NULL)
                    287:                return (EBADF);
                    288:
                    289:        if ((u_int)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
1.103     pk        290:            (u_int)new >= maxfiles) {
                    291:                simple_unlock(&fp->f_slock);
1.16      cgd       292:                return (EBADF);
1.103     pk        293:        }
1.77      thorpej   294:
1.17      cgd       295:        if (old == new) {
1.103     pk        296:                simple_unlock(&fp->f_slock);
1.17      cgd       297:                *retval = new;
1.16      cgd       298:                return (0);
1.17      cgd       299:        }
1.59      thorpej   300:
                    301:        FILE_USE(fp);
                    302:
1.16      cgd       303:        if (new >= fdp->fd_nfiles) {
1.59      thorpej   304:                if ((error = fdalloc(p, new, &i)) != 0) {
1.76      thorpej   305:                        if (error == ENOSPC) {
                    306:                                fdexpand(p);
1.110     fvdl      307:                                FILE_UNUSE(fp, p);
1.76      thorpej   308:                                goto restart;
                    309:                        }
1.110     fvdl      310:                        FILE_UNUSE(fp, p);
1.16      cgd       311:                        return (error);
1.59      thorpej   312:                }
1.16      cgd       313:                if (new != i)
                    314:                        panic("dup2: fdalloc");
1.117     yamt      315:        } else if (fdp->fd_ofiles[new] == NULL) {
                    316:                /*
                    317:                 * Mark `new' slot "used" only if it was empty.
                    318:                 */
                    319:                fd_used(fdp, new);
1.16      cgd       320:        }
1.59      thorpej   321:
1.75      thorpej   322:        /*
                    323:         * finishdup() will close the file that's in the `new'
                    324:         * slot, if there's one there.
                    325:         */
                    326:
1.59      thorpej   327:        /* finishdup() will unuse the descriptors for us */
1.110     fvdl      328:        return (finishdup(p, old, new, retval));
1.16      cgd       329: }
                    330:
                    331: /*
                    332:  * The file control system call.
                    333:  */
                    334: /* ARGSUSED */
1.38      christos  335: int
1.99      thorpej   336: sys_fcntl(struct lwp *l, void *v, register_t *retval)
1.36      thorpej   337: {
1.66      augustss  338:        struct sys_fcntl_args /* {
1.72      lukem     339:                syscallarg(int)         fd;
                    340:                syscallarg(int)         cmd;
                    341:                syscallarg(void *)      arg;
1.36      thorpej   342:        } */ *uap = v;
1.72      lukem     343:        struct filedesc *fdp;
                    344:        struct file     *fp;
1.99      thorpej   345:        struct proc     *p;
1.72      lukem     346:        struct vnode    *vp;
                    347:        int             fd, i, tmp, error, flg, cmd, newmin;
                    348:        struct flock    fl;
                    349:
1.99      thorpej   350:        p = l->l_proc;
1.72      lukem     351:        fd = SCARG(uap, fd);
1.122     christos  352:        cmd = SCARG(uap, cmd);
1.72      lukem     353:        fdp = p->p_fd;
                    354:        error = 0;
                    355:        flg = F_POSIX;
1.16      cgd       356:
1.122     christos  357:        switch (cmd) {
                    358:        case F_CLOSEM:
                    359:                if (fd < 0)
                    360:                        return EBADF;
                    361:                while (fdp->fd_lastfile >= fd)
                    362:                        fdrelease(p, fdp->fd_lastfile);
                    363:                return 0;
                    364:
                    365:        case F_MAXFD:
1.123     jdolecek  366:                *retval = fdp->fd_lastfile;
                    367:                return 0;
1.122     christos  368:
                    369:        default:
                    370:                /* Handled below */
                    371:                break;
                    372:        }
                    373:
1.75      thorpej   374:  restart:
1.77      thorpej   375:        if ((fp = fd_getfile(fdp, fd)) == NULL)
1.16      cgd       376:                return (EBADF);
1.59      thorpej   377:
                    378:        FILE_USE(fp);
                    379:
1.61      wrstuden  380:        if ((cmd & F_FSCTL)) {
1.110     fvdl      381:                error = fcntl_forfs(fd, p, cmd, SCARG(uap, arg));
1.61      wrstuden  382:                goto out;
                    383:        }
                    384:
                    385:        switch (cmd) {
1.17      cgd       386:
1.16      cgd       387:        case F_DUPFD:
1.30      cgd       388:                newmin = (long)SCARG(uap, arg);
1.27      mycroft   389:                if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
1.59      thorpej   390:                    (u_int)newmin >= maxfiles) {
                    391:                        error = EINVAL;
                    392:                        goto out;
                    393:                }
1.75      thorpej   394:                if ((error = fdalloc(p, newmin, &i)) != 0) {
1.76      thorpej   395:                        if (error == ENOSPC) {
                    396:                                fdexpand(p);
1.110     fvdl      397:                                FILE_UNUSE(fp, p);
1.75      thorpej   398:                                goto restart;
                    399:                        }
1.59      thorpej   400:                        goto out;
1.75      thorpej   401:                }
1.59      thorpej   402:
                    403:                /* finishdup() will unuse the descriptors for us */
1.110     fvdl      404:                return (finishdup(p, fd, i, retval));
1.16      cgd       405:
                    406:        case F_GETFD:
1.27      mycroft   407:                *retval = fdp->fd_ofileflags[fd] & UF_EXCLOSE ? 1 : 0;
1.59      thorpej   408:                break;
1.16      cgd       409:
                    410:        case F_SETFD:
1.27      mycroft   411:                if ((long)SCARG(uap, arg) & 1)
                    412:                        fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
                    413:                else
                    414:                        fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
1.59      thorpej   415:                break;
1.16      cgd       416:
                    417:        case F_GETFL:
                    418:                *retval = OFLAGS(fp->f_flag);
1.59      thorpej   419:                break;
1.16      cgd       420:
                    421:        case F_SETFL:
1.61      wrstuden  422:                tmp = FFLAGS((long)SCARG(uap, arg)) & FCNTLFLAGS;
1.110     fvdl      423:                error = (*fp->f_ops->fo_fcntl)(fp, F_SETFL, &tmp, p);
1.61      wrstuden  424:                if (error)
1.107     dsl       425:                        break;
                    426:                i = tmp ^ fp->f_flag;
                    427:                if (i & FNONBLOCK) {
                    428:                        int fl = tmp & FNONBLOCK;
1.110     fvdl      429:                        error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, &fl, p);
1.107     dsl       430:                        if (error)
                    431:                                goto reset_fcntl;
                    432:                }
                    433:                if (i & FASYNC) {
                    434:                        int fl = tmp & FASYNC;
1.110     fvdl      435:                        error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, &fl, p);
1.107     dsl       436:                        if (error) {
                    437:                                if (i & FNONBLOCK) {
                    438:                                        tmp = fp->f_flag & FNONBLOCK;
                    439:                                        (void)(*fp->f_ops->fo_ioctl)(fp,
1.110     fvdl      440:                                                FIONBIO, &tmp, p);
1.107     dsl       441:                                }
                    442:                                goto reset_fcntl;
                    443:                        }
                    444:                }
                    445:                fp->f_flag = (fp->f_flag & ~FCNTLFLAGS) | tmp;
                    446:                break;
                    447:            reset_fcntl:
1.110     fvdl      448:                (void)(*fp->f_ops->fo_fcntl)(fp, F_SETFL, &fp->f_flag, p);
1.59      thorpej   449:                break;
1.16      cgd       450:
                    451:        case F_GETOWN:
1.113     jdolecek  452:                error = (*fp->f_ops->fo_ioctl)(fp, FIOGETOWN, retval, p);
1.59      thorpej   453:                break;
1.16      cgd       454:
                    455:        case F_SETOWN:
1.113     jdolecek  456:                tmp = (int)(intptr_t) SCARG(uap, arg);
                    457:                error = (*fp->f_ops->fo_ioctl)(fp, FIOSETOWN, &tmp, p);
1.59      thorpej   458:                break;
1.16      cgd       459:
                    460:        case F_SETLKW:
                    461:                flg |= F_WAIT;
                    462:                /* Fall into F_SETLK */
                    463:
                    464:        case F_SETLK:
1.59      thorpej   465:                if (fp->f_type != DTYPE_VNODE) {
                    466:                        error = EINVAL;
                    467:                        goto out;
                    468:                }
1.16      cgd       469:                vp = (struct vnode *)fp->f_data;
                    470:                /* Copy in the lock structure */
1.106     dsl       471:                error = copyin(SCARG(uap, arg), &fl, sizeof(fl));
1.16      cgd       472:                if (error)
1.59      thorpej   473:                        goto out;
1.16      cgd       474:                if (fl.l_whence == SEEK_CUR)
                    475:                        fl.l_start += fp->f_offset;
                    476:                switch (fl.l_type) {
                    477:                case F_RDLCK:
1.59      thorpej   478:                        if ((fp->f_flag & FREAD) == 0) {
                    479:                                error = EBADF;
                    480:                                goto out;
                    481:                        }
1.16      cgd       482:                        p->p_flag |= P_ADVLOCK;
1.106     dsl       483:                        error = VOP_ADVLOCK(vp, p, F_SETLK, &fl, flg);
1.59      thorpej   484:                        goto out;
1.16      cgd       485:
                    486:                case F_WRLCK:
1.59      thorpej   487:                        if ((fp->f_flag & FWRITE) == 0) {
                    488:                                error = EBADF;
                    489:                                goto out;
                    490:                        }
1.16      cgd       491:                        p->p_flag |= P_ADVLOCK;
1.106     dsl       492:                        error = VOP_ADVLOCK(vp, p, F_SETLK, &fl, flg);
1.59      thorpej   493:                        goto out;
1.16      cgd       494:
                    495:                case F_UNLCK:
1.106     dsl       496:                        error = VOP_ADVLOCK(vp, p, F_UNLCK, &fl, F_POSIX);
1.59      thorpej   497:                        goto out;
1.16      cgd       498:
                    499:                default:
1.59      thorpej   500:                        error = EINVAL;
                    501:                        goto out;
1.16      cgd       502:                }
                    503:
                    504:        case F_GETLK:
1.59      thorpej   505:                if (fp->f_type != DTYPE_VNODE) {
                    506:                        error = EINVAL;
                    507:                        goto out;
                    508:                }
1.16      cgd       509:                vp = (struct vnode *)fp->f_data;
                    510:                /* Copy in the lock structure */
1.106     dsl       511:                error = copyin(SCARG(uap, arg), &fl, sizeof(fl));
1.16      cgd       512:                if (error)
1.59      thorpej   513:                        goto out;
1.16      cgd       514:                if (fl.l_whence == SEEK_CUR)
                    515:                        fl.l_start += fp->f_offset;
1.43      kleink    516:                if (fl.l_type != F_RDLCK &&
                    517:                    fl.l_type != F_WRLCK &&
1.59      thorpej   518:                    fl.l_type != F_UNLCK) {
                    519:                        error = EINVAL;
                    520:                        goto out;
                    521:                }
1.106     dsl       522:                error = VOP_ADVLOCK(vp, p, F_GETLK, &fl, F_POSIX);
1.38      christos  523:                if (error)
1.59      thorpej   524:                        goto out;
1.106     dsl       525:                error = copyout(&fl, SCARG(uap, arg), sizeof(fl));
1.59      thorpej   526:                break;
1.16      cgd       527:
                    528:        default:
1.59      thorpej   529:                error = EINVAL;
1.16      cgd       530:        }
1.59      thorpej   531:
                    532:  out:
1.110     fvdl      533:        FILE_UNUSE(fp, p);
1.59      thorpej   534:        return (error);
1.16      cgd       535: }
                    536:
                    537: /*
1.17      cgd       538:  * Common code for dup, dup2, and fcntl(F_DUPFD).
                    539:  */
                    540: int
1.110     fvdl      541: finishdup(struct proc *p, int old, int new, register_t *retval)
1.17      cgd       542: {
1.72      lukem     543:        struct filedesc *fdp;
1.110     fvdl      544:        struct file     *fp, *delfp;
1.72      lukem     545:
                    546:        fdp = p->p_fd;
1.59      thorpej   547:
                    548:        /*
1.75      thorpej   549:         * If there is a file in the new slot, remember it so we
                    550:         * can close it after we've finished the dup.  We need
                    551:         * to do it after the dup is finished, since closing
                    552:         * the file may block.
                    553:         *
1.59      thorpej   554:         * Note: `old' is already used for us.
1.117     yamt      555:         * Note: Caller already marked `new' slot "used".
1.59      thorpej   556:         */
1.75      thorpej   557:        delfp = fdp->fd_ofiles[new];
1.17      cgd       558:
                    559:        fp = fdp->fd_ofiles[old];
1.124   ! yamt      560:        KDASSERT(fp != NULL);
1.17      cgd       561:        fdp->fd_ofiles[new] = fp;
                    562:        fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
                    563:        fp->f_count++;
                    564:        *retval = new;
1.110     fvdl      565:        FILE_UNUSE(fp, p);
1.75      thorpej   566:
                    567:        if (delfp != NULL) {
1.103     pk        568:                simple_lock(&delfp->f_slock);
1.75      thorpej   569:                FILE_USE(delfp);
1.96      jdolecek  570:                if (new < fdp->fd_knlistsize)
1.110     fvdl      571:                        knote_fdclose(p, new);
                    572:                (void) closef(delfp, p);
1.75      thorpej   573:        }
1.17      cgd       574:        return (0);
1.65      thorpej   575: }
                    576:
                    577: void
1.72      lukem     578: fdremove(struct filedesc *fdp, int fd)
1.65      thorpej   579: {
                    580:
                    581:        fdp->fd_ofiles[fd] = NULL;
                    582:        fd_unused(fdp, fd);
1.17      cgd       583: }
                    584:
1.27      mycroft   585: int
1.110     fvdl      586: fdrelease(struct proc *p, int fd)
1.72      lukem     587: {
                    588:        struct filedesc *fdp;
1.110     fvdl      589:        struct file     **fpp, *fp;
1.27      mycroft   590:
1.72      lukem     591:        fdp = p->p_fd;
1.27      mycroft   592:        fpp = &fdp->fd_ofiles[fd];
                    593:        fp = *fpp;
                    594:        if (fp == NULL)
                    595:                return (EBADF);
1.59      thorpej   596:
1.103     pk        597:        simple_lock(&fp->f_slock);
                    598:        if (!FILE_IS_USABLE(fp)) {
                    599:                simple_unlock(&fp->f_slock);
                    600:                return (EBADF);
                    601:        }
                    602:
1.59      thorpej   603:        FILE_USE(fp);
                    604:
1.27      mycroft   605:        *fpp = NULL;
1.75      thorpej   606:        fdp->fd_ofileflags[fd] = 0;
1.96      jdolecek  607:        if (fd < fdp->fd_knlistsize)
1.110     fvdl      608:                knote_fdclose(p, fd);
1.27      mycroft   609:        fd_unused(fdp, fd);
1.110     fvdl      610:        return (closef(fp, p));
1.27      mycroft   611: }
                    612:
1.17      cgd       613: /*
1.16      cgd       614:  * Close a file descriptor.
                    615:  */
                    616: /* ARGSUSED */
1.38      christos  617: int
1.99      thorpej   618: sys_close(struct lwp *l, void *v, register_t *retval)
1.36      thorpej   619: {
1.37      mycroft   620:        struct sys_close_args /* {
1.72      lukem     621:                syscallarg(int) fd;
1.36      thorpej   622:        } */ *uap = v;
1.72      lukem     623:        int             fd;
                    624:        struct filedesc *fdp;
1.99      thorpej   625:        struct proc *p;
1.16      cgd       626:
1.99      thorpej   627:        p = l->l_proc;
1.72      lukem     628:        fd = SCARG(uap, fd);
                    629:        fdp = p->p_fd;
1.79      thorpej   630:
1.103     pk        631:        if ((u_int) fd >= fdp->fd_nfiles)
1.105     martin    632:                return (EBADF);
1.103     pk        633: #if 0
1.100     simonb    634:        if (fd_getfile(fdp, fd) == NULL)
1.16      cgd       635:                return (EBADF);
1.103     pk        636: #endif
1.79      thorpej   637:
1.110     fvdl      638:        return (fdrelease(p, fd));
1.16      cgd       639: }
                    640:
1.17      cgd       641: /*
                    642:  * Return status information about a file descriptor.
                    643:  */
1.16      cgd       644: /* ARGSUSED */
1.38      christos  645: int
1.99      thorpej   646: sys___fstat13(struct lwp *l, void *v, register_t *retval)
1.36      thorpej   647: {
1.66      augustss  648:        struct sys___fstat13_args /* {
1.72      lukem     649:                syscallarg(int)                 fd;
                    650:                syscallarg(struct stat *)       sb;
1.36      thorpej   651:        } */ *uap = v;
1.72      lukem     652:        int             fd;
                    653:        struct filedesc *fdp;
                    654:        struct file     *fp;
1.99      thorpej   655:        struct proc     *p;
1.72      lukem     656:        struct stat     ub;
                    657:        int             error;
1.16      cgd       658:
1.99      thorpej   659:        p = l->l_proc;
1.72      lukem     660:        fd = SCARG(uap, fd);
                    661:        fdp = p->p_fd;
1.77      thorpej   662:
                    663:        if ((fp = fd_getfile(fdp, fd)) == NULL)
1.16      cgd       664:                return (EBADF);
1.59      thorpej   665:
                    666:        FILE_USE(fp);
1.110     fvdl      667:        error = (*fp->f_ops->fo_stat)(fp, &ub, p);
                    668:        FILE_UNUSE(fp, p);
1.59      thorpej   669:
1.16      cgd       670:        if (error == 0)
1.52      perry     671:                error = copyout(&ub, SCARG(uap, sb), sizeof(ub));
1.73      jdolecek  672:
1.16      cgd       673:        return (error);
                    674: }
                    675:
                    676: /*
                    677:  * Return pathconf information about a file descriptor.
                    678:  */
                    679: /* ARGSUSED */
1.38      christos  680: int
1.99      thorpej   681: sys_fpathconf(struct lwp *l, void *v, register_t *retval)
1.36      thorpej   682: {
1.66      augustss  683:        struct sys_fpathconf_args /* {
1.72      lukem     684:                syscallarg(int) fd;
                    685:                syscallarg(int) name;
1.36      thorpej   686:        } */ *uap = v;
1.72      lukem     687:        int             fd;
                    688:        struct filedesc *fdp;
                    689:        struct file     *fp;
1.99      thorpej   690:        struct proc     *p;
1.72      lukem     691:        struct vnode    *vp;
                    692:        int             error;
                    693:
1.99      thorpej   694:        p = l->l_proc;
1.72      lukem     695:        fd = SCARG(uap, fd);
                    696:        fdp = p->p_fd;
                    697:        error = 0;
1.17      cgd       698:
1.77      thorpej   699:        if ((fp = fd_getfile(fdp, fd)) == NULL)
1.17      cgd       700:                return (EBADF);
1.59      thorpej   701:
                    702:        FILE_USE(fp);
                    703:
1.17      cgd       704:        switch (fp->f_type) {
1.16      cgd       705:
1.17      cgd       706:        case DTYPE_SOCKET:
1.78      jdolecek  707:        case DTYPE_PIPE:
1.25      cgd       708:                if (SCARG(uap, name) != _PC_PIPE_BUF)
1.59      thorpej   709:                        error = EINVAL;
                    710:                else
                    711:                        *retval = PIPE_BUF;
                    712:                break;
1.17      cgd       713:
                    714:        case DTYPE_VNODE:
                    715:                vp = (struct vnode *)fp->f_data;
1.59      thorpej   716:                error = VOP_PATHCONF(vp, SCARG(uap, name), retval);
                    717:                break;
1.17      cgd       718:
1.96      jdolecek  719:        case DTYPE_KQUEUE:
                    720:                error = EINVAL;
                    721:                break;
                    722:
1.17      cgd       723:        default:
1.93      thorpej   724:                error = EOPNOTSUPP;
                    725:                break;
1.17      cgd       726:        }
1.59      thorpej   727:
1.110     fvdl      728:        FILE_UNUSE(fp, p);
1.59      thorpej   729:        return (error);
1.16      cgd       730: }
                    731:
                    732: /*
                    733:  * Allocate a file descriptor for the process.
                    734:  */
1.76      thorpej   735: int    fdexpanded;             /* XXX: what else uses this? */
1.16      cgd       736:
1.38      christos  737: int
1.72      lukem     738: fdalloc(struct proc *p, int want, int *result)
                    739: {
                    740:        struct filedesc *fdp;
1.76      thorpej   741:        int i, lim, last;
1.115     provos    742:        u_int off, new;
1.72      lukem     743:
                    744:        fdp = p->p_fd;
1.16      cgd       745:
                    746:        /*
                    747:         * Search for a free descriptor starting at the higher
                    748:         * of want or fd_freefile.  If that fails, consider
                    749:         * expanding the ofile array.
                    750:         */
1.17      cgd       751:        lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
1.90      enami     752:        last = min(fdp->fd_nfiles, lim);
1.115     provos    753:  again:
1.90      enami     754:        if ((i = want) < fdp->fd_freefile)
                    755:                i = fdp->fd_freefile;
1.115     provos    756:        off = i >> NDENTRYSHIFT;
                    757:        new = find_next_zero(fdp->fd_himap, off,
                    758:            (last + NDENTRIES - 1) >> NDENTRYSHIFT);
                    759:        if (new != -1) {
                    760:                i = find_next_zero(&fdp->fd_lomap[new],
                    761:                    new > off ? 0 : i & NDENTRYMASK, NDENTRIES);
                    762:                if (i == -1) {
                    763:                        /*
                    764:                         * free file descriptor in this block was
                    765:                         * below want, try again with higher want.
                    766:                         */
                    767:                        want = (new + 1) << NDENTRYSHIFT;
                    768:                        goto again;
                    769:                }
                    770:                i += (new << NDENTRYSHIFT);
                    771:                if (i < last) {
                    772:                        if (fdp->fd_ofiles[i] == NULL) {
                    773:                                fd_used(fdp, i);
                    774:                                if (want <= fdp->fd_freefile)
                    775:                                        fdp->fd_freefile = i;
                    776:                                *result = i;
                    777:                                return (0);
                    778:                        }
1.16      cgd       779:                }
1.90      enami     780:        }
1.16      cgd       781:
1.90      enami     782:        /* No space in current array.  Expand? */
                    783:        if (fdp->fd_nfiles >= lim)
                    784:                return (EMFILE);
1.76      thorpej   785:
1.90      enami     786:        /* Let the caller do it. */
                    787:        return (ENOSPC);
1.16      cgd       788: }
                    789:
1.76      thorpej   790: void
                    791: fdexpand(struct proc *p)
                    792: {
                    793:        struct filedesc *fdp;
                    794:        int             i, nfiles;
                    795:        struct file     **newofile;
                    796:        char            *newofileflags;
1.115     provos    797:        uint32_t        *newhimap, *newlomap;
1.76      thorpej   798:
                    799:        fdp = p->p_fd;
                    800:
                    801:        if (fdp->fd_nfiles < NDEXTENT)
                    802:                nfiles = NDEXTENT;
                    803:        else
                    804:                nfiles = 2 * fdp->fd_nfiles;
                    805:        newofile = malloc(nfiles * OFILESIZE, M_FILEDESC, M_WAITOK);
                    806:        newofileflags = (char *) &newofile[nfiles];
                    807:        /*
                    808:         * Copy the existing ofile and ofileflags arrays
                    809:         * and zero the new portion of each array.
                    810:         */
                    811:        memcpy(newofile, fdp->fd_ofiles,
1.89      enami     812:            (i = sizeof(struct file *) * fdp->fd_nfiles));
1.76      thorpej   813:        memset((char *)newofile + i, 0,
                    814:            nfiles * sizeof(struct file *) - i);
                    815:        memcpy(newofileflags, fdp->fd_ofileflags,
                    816:            (i = sizeof(char) * fdp->fd_nfiles));
                    817:        memset(newofileflags + i, 0, nfiles * sizeof(char) - i);
                    818:        if (fdp->fd_nfiles > NDFILE)
                    819:                free(fdp->fd_ofiles, M_FILEDESC);
1.115     provos    820:
                    821:        if (NDHISLOTS(nfiles) > NDHISLOTS(fdp->fd_nfiles)) {
                    822:                newhimap = malloc(NDHISLOTS(nfiles) * sizeof(uint32_t),
                    823:                    M_FILEDESC, M_WAITOK);
                    824:                newlomap = malloc(NDLOSLOTS(nfiles) * sizeof(uint32_t),
                    825:                    M_FILEDESC, M_WAITOK);
                    826:
                    827:                memcpy(newhimap, fdp->fd_himap,
                    828:                    (i = NDHISLOTS(fdp->fd_nfiles) * sizeof(uint32_t)));
                    829:                memset((char *)newhimap + i, 0,
                    830:                    NDHISLOTS(nfiles) * sizeof(uint32_t) - i);
                    831:
                    832:                memcpy(newlomap, fdp->fd_lomap,
                    833:                    (i = NDLOSLOTS(fdp->fd_nfiles) * sizeof(uint32_t)));
                    834:                memset((char *)newlomap + i, 0,
                    835:                    NDLOSLOTS(nfiles) * sizeof(uint32_t) - i);
                    836:
                    837:                if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
                    838:                        free(fdp->fd_himap, M_FILEDESC);
                    839:                        free(fdp->fd_lomap, M_FILEDESC);
                    840:                }
                    841:                fdp->fd_himap = newhimap;
                    842:                fdp->fd_lomap = newlomap;
                    843:        }
                    844:
1.76      thorpej   845:        fdp->fd_ofiles = newofile;
                    846:        fdp->fd_ofileflags = newofileflags;
                    847:        fdp->fd_nfiles = nfiles;
                    848:        fdexpanded++;
                    849: }
                    850:
1.16      cgd       851: /*
                    852:  * Check to see whether n user file descriptors
                    853:  * are available to the process p.
                    854:  */
1.38      christos  855: int
1.72      lukem     856: fdavail(struct proc *p, int n)
                    857: {
                    858:        struct filedesc *fdp;
                    859:        struct file     **fpp;
                    860:        int             i, lim;
1.16      cgd       861:
1.72      lukem     862:        fdp = p->p_fd;
1.17      cgd       863:        lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
                    864:        if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
1.16      cgd       865:                return (1);
                    866:        fpp = &fdp->fd_ofiles[fdp->fd_freefile];
1.56      sommerfe  867:        for (i = min(lim,fdp->fd_nfiles) - fdp->fd_freefile; --i >= 0; fpp++)
1.16      cgd       868:                if (*fpp == NULL && --n <= 0)
                    869:                        return (1);
                    870:        return (0);
                    871: }
                    872:
                    873: /*
1.55      thorpej   874:  * Initialize the data structures necessary for managing files.
                    875:  */
                    876: void
1.72      lukem     877: finit(void)
1.55      thorpej   878: {
                    879:
                    880:        pool_init(&file_pool, sizeof(struct file), 0, 0, 0, "filepl",
1.85      thorpej   881:            &pool_allocator_nointr);
1.58      thorpej   882:        pool_init(&cwdi_pool, sizeof(struct cwdinfo), 0, 0, 0, "cwdipl",
1.85      thorpej   883:            &pool_allocator_nointr);
1.64      thorpej   884:        pool_init(&filedesc0_pool, sizeof(struct filedesc0), 0, 0, 0, "fdescpl",
1.85      thorpej   885:            &pool_allocator_nointr);
1.55      thorpej   886: }
                    887:
                    888: /*
1.16      cgd       889:  * Create a new open file structure and allocate
1.98      wiz       890:  * a file descriptor for the process that refers to it.
1.16      cgd       891:  */
1.38      christos  892: int
1.72      lukem     893: falloc(struct proc *p, struct file **resultfp, int *resultfd)
1.16      cgd       894: {
1.72      lukem     895:        struct file     *fp, *fq;
                    896:        int             error, i;
1.16      cgd       897:
1.75      thorpej   898:  restart:
                    899:        if ((error = fdalloc(p, 0, &i)) != 0) {
1.76      thorpej   900:                if (error == ENOSPC) {
                    901:                        fdexpand(p);
1.75      thorpej   902:                        goto restart;
1.76      thorpej   903:                }
1.16      cgd       904:                return (error);
1.75      thorpej   905:        }
1.102     pk        906:
                    907:        fp = pool_get(&file_pool, PR_WAITOK);
                    908:        simple_lock(&filelist_slock);
1.16      cgd       909:        if (nfiles >= maxfiles) {
1.69      jdolecek  910:                tablefull("file", "increase kern.maxfiles or MAXFILES");
1.102     pk        911:                simple_unlock(&filelist_slock);
1.115     provos    912:                fd_unused(p->p_fd, i);
1.102     pk        913:                pool_put(&file_pool, fp);
1.16      cgd       914:                return (ENFILE);
                    915:        }
                    916:        /*
                    917:         * Allocate a new file descriptor.
                    918:         * If the process has file descriptor zero open, add to the list
                    919:         * of open files at that point, otherwise put it at the front of
                    920:         * the list of open files.
                    921:         */
                    922:        nfiles++;
1.53      perry     923:        memset(fp, 0, sizeof(struct file));
1.83      jdolecek  924:        fp->f_iflags = FIF_LARVAL;
1.38      christos  925:        if ((fq = p->p_fd->fd_ofiles[0]) != NULL) {
1.24      mycroft   926:                LIST_INSERT_AFTER(fq, fp, f_list);
                    927:        } else {
                    928:                LIST_INSERT_HEAD(&filehead, fp, f_list);
                    929:        }
1.102     pk        930:        simple_unlock(&filelist_slock);
1.124   ! yamt      931:        KDASSERT(p->p_fd->fd_ofiles[i] == NULL);
1.16      cgd       932:        p->p_fd->fd_ofiles[i] = fp;
1.103     pk        933:        simple_lock_init(&fp->f_slock);
1.16      cgd       934:        fp->f_count = 1;
                    935:        fp->f_cred = p->p_ucred;
                    936:        crhold(fp->f_cred);
1.59      thorpej   937:        if (resultfp) {
1.103     pk        938:                fp->f_usecount = 1;
1.16      cgd       939:                *resultfp = fp;
1.59      thorpej   940:        }
1.16      cgd       941:        if (resultfd)
                    942:                *resultfd = i;
                    943:        return (0);
                    944: }
                    945:
                    946: /*
                    947:  * Free a file descriptor.
                    948:  */
1.38      christos  949: void
1.72      lukem     950: ffree(struct file *fp)
1.16      cgd       951: {
1.59      thorpej   952:
                    953: #ifdef DIAGNOSTIC
                    954:        if (fp->f_usecount)
                    955:                panic("ffree");
                    956: #endif
                    957:
1.102     pk        958:        simple_lock(&filelist_slock);
1.24      mycroft   959:        LIST_REMOVE(fp, f_list);
1.16      cgd       960:        crfree(fp->f_cred);
                    961: #ifdef DIAGNOSTIC
1.103     pk        962:        fp->f_count = 0; /* What's the point? */
1.16      cgd       963: #endif
                    964:        nfiles--;
1.102     pk        965:        simple_unlock(&filelist_slock);
1.55      thorpej   966:        pool_put(&file_pool, fp);
1.48      thorpej   967: }
                    968:
                    969: /*
1.58      thorpej   970:  * Create an initial cwdinfo structure, using the same current and root
                    971:  * directories as p.
                    972:  */
                    973: struct cwdinfo *
1.72      lukem     974: cwdinit(struct proc *p)
1.58      thorpej   975: {
                    976:        struct cwdinfo *cwdi;
                    977:
                    978:        cwdi = pool_get(&cwdi_pool, PR_WAITOK);
                    979:
                    980:        cwdi->cwdi_cdir = p->p_cwdi->cwdi_cdir;
1.63      thorpej   981:        if (cwdi->cwdi_cdir)
                    982:                VREF(cwdi->cwdi_cdir);
1.58      thorpej   983:        cwdi->cwdi_rdir = p->p_cwdi->cwdi_rdir;
                    984:        if (cwdi->cwdi_rdir)
                    985:                VREF(cwdi->cwdi_rdir);
1.60      christos  986:        cwdi->cwdi_cmask =  p->p_cwdi->cwdi_cmask;
1.58      thorpej   987:        cwdi->cwdi_refcnt = 1;
                    988:
                    989:        return (cwdi);
                    990: }
                    991:
                    992: /*
                    993:  * Make p2 share p1's cwdinfo.
                    994:  */
                    995: void
1.72      lukem     996: cwdshare(struct proc *p1, struct proc *p2)
1.58      thorpej   997: {
                    998:
                    999:        p2->p_cwdi = p1->p_cwdi;
                   1000:        p1->p_cwdi->cwdi_refcnt++;
                   1001: }
                   1002:
                   1003: /*
                   1004:  * Make this process not share its cwdinfo structure, maintaining
                   1005:  * all cwdinfo state.
                   1006:  */
                   1007: void
1.72      lukem    1008: cwdunshare(struct proc *p)
1.58      thorpej  1009: {
                   1010:        struct cwdinfo *newcwdi;
                   1011:
                   1012:        if (p->p_cwdi->cwdi_refcnt == 1)
                   1013:                return;
                   1014:
                   1015:        newcwdi = cwdinit(p);
                   1016:        cwdfree(p);
                   1017:        p->p_cwdi = newcwdi;
                   1018: }
                   1019:
                   1020: /*
                   1021:  * Release a cwdinfo structure.
                   1022:  */
                   1023: void
1.72      lukem    1024: cwdfree(struct proc *p)
1.58      thorpej  1025: {
1.72      lukem    1026:        struct cwdinfo *cwdi;
1.58      thorpej  1027:
1.72      lukem    1028:        cwdi = p->p_cwdi;
1.58      thorpej  1029:        if (--cwdi->cwdi_refcnt > 0)
                   1030:                return;
                   1031:
                   1032:        p->p_cwdi = NULL;
                   1033:
                   1034:        vrele(cwdi->cwdi_cdir);
                   1035:        if (cwdi->cwdi_rdir)
                   1036:                vrele(cwdi->cwdi_rdir);
                   1037:        pool_put(&cwdi_pool, cwdi);
                   1038: }
                   1039:
                   1040: /*
1.48      thorpej  1041:  * Create an initial filedesc structure, using the same current and root
                   1042:  * directories as p.
                   1043:  */
                   1044: struct filedesc *
1.72      lukem    1045: fdinit(struct proc *p)
1.48      thorpej  1046: {
                   1047:        struct filedesc0 *newfdp;
                   1048:
1.64      thorpej  1049:        newfdp = pool_get(&filedesc0_pool, PR_WAITOK);
1.53      perry    1050:        memset(newfdp, 0, sizeof(struct filedesc0));
1.48      thorpej  1051:
                   1052:        fdinit1(newfdp);
                   1053:
                   1054:        return (&newfdp->fd_fd);
                   1055: }
                   1056:
                   1057: /*
                   1058:  * Initialize a file descriptor table.
                   1059:  */
                   1060: void
1.72      lukem    1061: fdinit1(struct filedesc0 *newfdp)
1.48      thorpej  1062: {
                   1063:
                   1064:        newfdp->fd_fd.fd_refcnt = 1;
                   1065:        newfdp->fd_fd.fd_ofiles = newfdp->fd_dfiles;
                   1066:        newfdp->fd_fd.fd_ofileflags = newfdp->fd_dfileflags;
                   1067:        newfdp->fd_fd.fd_nfiles = NDFILE;
1.96      jdolecek 1068:        newfdp->fd_fd.fd_knlistsize = -1;
1.115     provos   1069:        newfdp->fd_fd.fd_himap = newfdp->fd_dhimap;
                   1070:        newfdp->fd_fd.fd_lomap = newfdp->fd_dlomap;
1.48      thorpej  1071: }
                   1072:
                   1073: /*
                   1074:  * Make p2 share p1's filedesc structure.
                   1075:  */
                   1076: void
1.72      lukem    1077: fdshare(struct proc *p1, struct proc *p2)
1.48      thorpej  1078: {
                   1079:
                   1080:        p2->p_fd = p1->p_fd;
                   1081:        p1->p_fd->fd_refcnt++;
                   1082: }
                   1083:
                   1084: /*
                   1085:  * Make this process not share its filedesc structure, maintaining
                   1086:  * all file descriptor state.
                   1087:  */
                   1088: void
1.110     fvdl     1089: fdunshare(struct proc *p)
1.48      thorpej  1090: {
                   1091:        struct filedesc *newfd;
                   1092:
                   1093:        if (p->p_fd->fd_refcnt == 1)
                   1094:                return;
                   1095:
                   1096:        newfd = fdcopy(p);
1.110     fvdl     1097:        fdfree(p);
1.48      thorpej  1098:        p->p_fd = newfd;
                   1099: }
                   1100:
                   1101: /*
                   1102:  * Clear a process's fd table.
                   1103:  */
                   1104: void
1.110     fvdl     1105: fdclear(struct proc *p)
1.48      thorpej  1106: {
                   1107:        struct filedesc *newfd;
                   1108:
                   1109:        newfd = fdinit(p);
1.110     fvdl     1110:        fdfree(p);
1.48      thorpej  1111:        p->p_fd = newfd;
1.16      cgd      1112: }
                   1113:
                   1114: /*
                   1115:  * Copy a filedesc structure.
                   1116:  */
                   1117: struct filedesc *
1.72      lukem    1118: fdcopy(struct proc *p)
1.16      cgd      1119: {
1.72      lukem    1120:        struct filedesc *newfdp, *fdp;
                   1121:        struct file     **fpp;
                   1122:        int             i;
1.16      cgd      1123:
1.72      lukem    1124:        fdp = p->p_fd;
1.64      thorpej  1125:        newfdp = pool_get(&filedesc0_pool, PR_WAITOK);
1.53      perry    1126:        memcpy(newfdp, fdp, sizeof(struct filedesc));
1.16      cgd      1127:        newfdp->fd_refcnt = 1;
                   1128:
                   1129:        /*
                   1130:         * If the number of open files fits in the internal arrays
                   1131:         * of the open file structure, use them, otherwise allocate
                   1132:         * additional memory for the number of descriptors currently
                   1133:         * in use.
                   1134:         */
                   1135:        if (newfdp->fd_lastfile < NDFILE) {
                   1136:                newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
                   1137:                newfdp->fd_ofileflags =
                   1138:                    ((struct filedesc0 *) newfdp)->fd_dfileflags;
                   1139:                i = NDFILE;
                   1140:        } else {
                   1141:                /*
                   1142:                 * Compute the smallest multiple of NDEXTENT needed
                   1143:                 * for the file descriptors currently in use,
                   1144:                 * allowing the table to shrink.
                   1145:                 */
                   1146:                i = newfdp->fd_nfiles;
1.27      mycroft  1147:                while (i >= 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
1.16      cgd      1148:                        i /= 2;
1.64      thorpej  1149:                newfdp->fd_ofiles = malloc(i * OFILESIZE, M_FILEDESC, M_WAITOK);
1.16      cgd      1150:                newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
                   1151:        }
1.115     provos   1152:        if (NDHISLOTS(i) <= NDHISLOTS(NDFILE)) {
                   1153:                newfdp->fd_himap =
                   1154:                    ((struct filedesc0 *) newfdp)->fd_dhimap;
                   1155:                newfdp->fd_lomap =
                   1156:                    ((struct filedesc0 *) newfdp)->fd_dlomap;
                   1157:        } else {
                   1158:                newfdp->fd_himap = malloc(NDHISLOTS(i) * sizeof(uint32_t),
                   1159:                    M_FILEDESC, M_WAITOK);
                   1160:                newfdp->fd_lomap = malloc(NDLOSLOTS(i) * sizeof(uint32_t),
                   1161:                    M_FILEDESC, M_WAITOK);
                   1162:        }
                   1163:
1.16      cgd      1164:        newfdp->fd_nfiles = i;
1.53      perry    1165:        memcpy(newfdp->fd_ofiles, fdp->fd_ofiles, i * sizeof(struct file **));
                   1166:        memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags, i * sizeof(char));
1.120     yamt     1167:        if (i < NDENTRIES * NDENTRIES)
                   1168:                i = NDENTRIES * NDENTRIES; /* size of inlined bitmaps */
1.115     provos   1169:        memcpy(newfdp->fd_himap, fdp->fd_himap, NDHISLOTS(i)*sizeof(uint32_t));
                   1170:        memcpy(newfdp->fd_lomap, fdp->fd_lomap, NDLOSLOTS(i)*sizeof(uint32_t));
1.96      jdolecek 1171:        /*
                   1172:         * kq descriptors cannot be copied.
                   1173:         */
                   1174:        if (newfdp->fd_knlistsize != -1) {
                   1175:                fpp = newfdp->fd_ofiles;
1.116     provos   1176:                for (i = 0; i <= newfdp->fd_lastfile; i++, fpp++) {
1.96      jdolecek 1177:                        if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE)
1.116     provos   1178:                                fdremove(newfdp, i);
1.96      jdolecek 1179:                }
                   1180:                newfdp->fd_knlist = NULL;
                   1181:                newfdp->fd_knlistsize = -1;
                   1182:                newfdp->fd_knhash = NULL;
                   1183:                newfdp->fd_knhashmask = 0;
                   1184:        }
1.16      cgd      1185:        fpp = newfdp->fd_ofiles;
1.27      mycroft  1186:        for (i = newfdp->fd_lastfile; i >= 0; i--, fpp++)
1.16      cgd      1187:                if (*fpp != NULL)
                   1188:                        (*fpp)->f_count++;
                   1189:        return (newfdp);
                   1190: }
                   1191:
                   1192: /*
                   1193:  * Release a filedesc structure.
                   1194:  */
                   1195: void
1.110     fvdl     1196: fdfree(struct proc *p)
1.16      cgd      1197: {
1.72      lukem    1198:        struct filedesc *fdp;
                   1199:        struct file     **fpp, *fp;
                   1200:        int             i;
1.16      cgd      1201:
1.72      lukem    1202:        fdp = p->p_fd;
1.16      cgd      1203:        if (--fdp->fd_refcnt > 0)
                   1204:                return;
                   1205:        fpp = fdp->fd_ofiles;
1.32      mycroft  1206:        for (i = fdp->fd_lastfile; i >= 0; i--, fpp++) {
                   1207:                fp = *fpp;
                   1208:                if (fp != NULL) {
                   1209:                        *fpp = NULL;
1.103     pk       1210:                        simple_lock(&fp->f_slock);
1.59      thorpej  1211:                        FILE_USE(fp);
1.96      jdolecek 1212:                        if (i < fdp->fd_knlistsize)
1.110     fvdl     1213:                                knote_fdclose(p, fdp->fd_lastfile - i);
                   1214:                        (void) closef(fp, p);
1.32      mycroft  1215:                }
                   1216:        }
                   1217:        p->p_fd = NULL;
1.16      cgd      1218:        if (fdp->fd_nfiles > NDFILE)
1.64      thorpej  1219:                free(fdp->fd_ofiles, M_FILEDESC);
1.115     provos   1220:        if (NDHISLOTS(fdp->fd_nfiles) > NDHISLOTS(NDFILE)) {
                   1221:                free(fdp->fd_himap, M_FILEDESC);
                   1222:                free(fdp->fd_lomap, M_FILEDESC);
                   1223:        }
1.96      jdolecek 1224:        if (fdp->fd_knlist)
                   1225:                free(fdp->fd_knlist, M_KEVENT);
                   1226:        if (fdp->fd_knhash)
                   1227:                hashdone(fdp->fd_knhash, M_KEVENT);
1.64      thorpej  1228:        pool_put(&filedesc0_pool, fdp);
1.16      cgd      1229: }
                   1230:
                   1231: /*
                   1232:  * Internal form of close.
                   1233:  * Decrement reference count on file structure.
1.17      cgd      1234:  * Note: p may be NULL when closing a file
                   1235:  * that was being passed in a message.
1.59      thorpej  1236:  *
                   1237:  * Note: we expect the caller is holding a usecount, and expects us
                   1238:  * to drop it (the caller thinks the file is going away forever).
1.16      cgd      1239:  */
1.38      christos 1240: int
1.110     fvdl     1241: closef(struct file *fp, struct proc *p)
1.72      lukem    1242: {
                   1243:        struct vnode    *vp;
                   1244:        struct flock    lf;
                   1245:        int             error;
1.16      cgd      1246:
                   1247:        if (fp == NULL)
                   1248:                return (0);
1.59      thorpej  1249:
1.16      cgd      1250:        /*
                   1251:         * POSIX record locking dictates that any close releases ALL
                   1252:         * locks owned by this process.  This is handled by setting
                   1253:         * a flag in the unlock to free ONLY locks obeying POSIX
                   1254:         * semantics, and not to free BSD-style file locks.
1.17      cgd      1255:         * If the descriptor was in a message, POSIX-style locks
                   1256:         * aren't passed with the descriptor.
1.16      cgd      1257:         */
                   1258:        if (p && (p->p_flag & P_ADVLOCK) && fp->f_type == DTYPE_VNODE) {
                   1259:                lf.l_whence = SEEK_SET;
                   1260:                lf.l_start = 0;
                   1261:                lf.l_len = 0;
                   1262:                lf.l_type = F_UNLCK;
                   1263:                vp = (struct vnode *)fp->f_data;
1.106     dsl      1264:                (void) VOP_ADVLOCK(vp, p, F_UNLCK, &lf, F_POSIX);
1.16      cgd      1265:        }
1.59      thorpej  1266:
                   1267:        /*
                   1268:         * If WANTCLOSE is set, then the reference count on the file
                   1269:         * is 0, but there were multiple users of the file.  This can
                   1270:         * happen if a filedesc structure is shared by multiple
                   1271:         * processes.
                   1272:         */
1.103     pk       1273:        simple_lock(&fp->f_slock);
1.83      jdolecek 1274:        if (fp->f_iflags & FIF_WANTCLOSE) {
1.59      thorpej  1275:                /*
                   1276:                 * Another user of the file is already closing, and is
                   1277:                 * simply waiting for other users of the file to drain.
                   1278:                 * Release our usecount, and wake up the closer if it
                   1279:                 * is the only remaining use.
                   1280:                 */
                   1281: #ifdef DIAGNOSTIC
                   1282:                if (fp->f_count != 0)
                   1283:                        panic("closef: wantclose and count != 0");
                   1284:                if (fp->f_usecount < 2)
                   1285:                        panic("closef: wantclose and usecount < 2");
                   1286: #endif
                   1287:                if (--fp->f_usecount == 1)
                   1288:                        wakeup(&fp->f_usecount);
1.103     pk       1289:                simple_unlock(&fp->f_slock);
1.16      cgd      1290:                return (0);
1.59      thorpej  1291:        } else {
                   1292:                /*
                   1293:                 * Decrement the reference count.  If we were not the
                   1294:                 * last reference, then release our use and just
                   1295:                 * return.
                   1296:                 */
                   1297:                if (--fp->f_count > 0) {
                   1298: #ifdef DIAGNOSTIC
                   1299:                        if (fp->f_usecount < 1)
                   1300:                                panic("closef: no wantclose and usecount < 1");
                   1301: #endif
                   1302:                        fp->f_usecount--;
1.103     pk       1303:                        simple_unlock(&fp->f_slock);
1.59      thorpej  1304:                        return (0);
                   1305:                }
                   1306:        }
                   1307:
                   1308:        /*
                   1309:         * The reference count is now 0.  However, there may be
                   1310:         * multiple potential users of this file.  This can happen
                   1311:         * if multiple processes shared a single filedesc structure.
                   1312:         *
                   1313:         * Notify these potential users that the file is closing.
                   1314:         * This will prevent them from adding additional uses to
                   1315:         * the file.
                   1316:         */
1.83      jdolecek 1317:        fp->f_iflags |= FIF_WANTCLOSE;
1.59      thorpej  1318:
                   1319:        /*
                   1320:         * We expect the caller to add a use to the file.  So, if we
                   1321:         * are the last user, usecount will be 1.  If it is not, we
                   1322:         * must wait for the usecount to drain.  When it drains back
                   1323:         * to 1, we will be awakened so that we may proceed with the
                   1324:         * close.
                   1325:         */
                   1326: #ifdef DIAGNOSTIC
                   1327:        if (fp->f_usecount < 1)
                   1328:                panic("closef: usecount < 1");
                   1329: #endif
                   1330:        while (fp->f_usecount > 1)
1.103     pk       1331:                (void) ltsleep(&fp->f_usecount, PRIBIO, "closef", 0,
                   1332:                                &fp->f_slock);
1.59      thorpej  1333: #ifdef DIAGNOSTIC
                   1334:        if (fp->f_usecount != 1)
                   1335:                panic("closef: usecount != 1");
                   1336: #endif
                   1337:
1.103     pk       1338:        simple_unlock(&fp->f_slock);
1.16      cgd      1339:        if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
                   1340:                lf.l_whence = SEEK_SET;
                   1341:                lf.l_start = 0;
                   1342:                lf.l_len = 0;
                   1343:                lf.l_type = F_UNLCK;
                   1344:                vp = (struct vnode *)fp->f_data;
1.106     dsl      1345:                (void) VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK);
1.16      cgd      1346:        }
1.17      cgd      1347:        if (fp->f_ops)
1.110     fvdl     1348:                error = (*fp->f_ops->fo_close)(fp, p);
1.17      cgd      1349:        else
                   1350:                error = 0;
1.59      thorpej  1351:
                   1352:        /* Nothing references the file now, drop the final use (us). */
                   1353:        fp->f_usecount--;
                   1354:
1.16      cgd      1355:        ffree(fp);
                   1356:        return (error);
                   1357: }
                   1358:
                   1359: /*
                   1360:  * Apply an advisory lock on a file descriptor.
                   1361:  *
                   1362:  * Just attempt to get a record lock of the requested type on
                   1363:  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
                   1364:  */
                   1365: /* ARGSUSED */
1.38      christos 1366: int
1.99      thorpej  1367: sys_flock(struct lwp *l, void *v, register_t *retval)
1.36      thorpej  1368: {
1.66      augustss 1369:        struct sys_flock_args /* {
1.72      lukem    1370:                syscallarg(int) fd;
                   1371:                syscallarg(int) how;
1.36      thorpej  1372:        } */ *uap = v;
1.72      lukem    1373:        int             fd, how, error;
1.99      thorpej  1374:        struct proc     *p;
1.72      lukem    1375:        struct filedesc *fdp;
                   1376:        struct file     *fp;
                   1377:        struct vnode    *vp;
                   1378:        struct flock    lf;
1.16      cgd      1379:
1.99      thorpej  1380:        p = l->l_proc;
1.72      lukem    1381:        fd = SCARG(uap, fd);
                   1382:        how = SCARG(uap, how);
                   1383:        fdp = p->p_fd;
                   1384:        error = 0;
1.77      thorpej  1385:
                   1386:        if ((fp = fd_getfile(fdp, fd)) == NULL)
1.16      cgd      1387:                return (EBADF);
1.59      thorpej  1388:
                   1389:        FILE_USE(fp);
                   1390:
                   1391:        if (fp->f_type != DTYPE_VNODE) {
                   1392:                error = EOPNOTSUPP;
                   1393:                goto out;
                   1394:        }
                   1395:
1.16      cgd      1396:        vp = (struct vnode *)fp->f_data;
                   1397:        lf.l_whence = SEEK_SET;
                   1398:        lf.l_start = 0;
                   1399:        lf.l_len = 0;
1.27      mycroft  1400:        if (how & LOCK_UN) {
1.16      cgd      1401:                lf.l_type = F_UNLCK;
                   1402:                fp->f_flag &= ~FHASLOCK;
1.106     dsl      1403:                error = VOP_ADVLOCK(vp, fp, F_UNLCK, &lf, F_FLOCK);
1.59      thorpej  1404:                goto out;
1.16      cgd      1405:        }
1.27      mycroft  1406:        if (how & LOCK_EX)
1.16      cgd      1407:                lf.l_type = F_WRLCK;
1.27      mycroft  1408:        else if (how & LOCK_SH)
1.16      cgd      1409:                lf.l_type = F_RDLCK;
1.59      thorpej  1410:        else {
                   1411:                error = EINVAL;
                   1412:                goto out;
                   1413:        }
1.16      cgd      1414:        fp->f_flag |= FHASLOCK;
1.27      mycroft  1415:        if (how & LOCK_NB)
1.106     dsl      1416:                error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, F_FLOCK);
1.59      thorpej  1417:        else
1.106     dsl      1418:                error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf,
1.59      thorpej  1419:                    F_FLOCK|F_WAIT);
                   1420:  out:
1.110     fvdl     1421:        FILE_UNUSE(fp, p);
1.59      thorpej  1422:        return (error);
1.16      cgd      1423: }
                   1424:
                   1425: /*
                   1426:  * File Descriptor pseudo-device driver (/dev/fd/).
                   1427:  *
                   1428:  * Opening minor device N dup()s the file (if any) connected to file
                   1429:  * descriptor N belonging to the calling process.  Note that this driver
                   1430:  * consists of only the ``open()'' routine, because all subsequent
                   1431:  * references to this file will be direct to the other driver.
                   1432:  */
                   1433: /* ARGSUSED */
1.28      mycroft  1434: int
1.110     fvdl     1435: filedescopen(dev_t dev, int mode, int type, struct proc *p)
1.16      cgd      1436: {
                   1437:
1.28      mycroft  1438:        /*
1.112     jdolecek 1439:         * XXX Kludge: set dupfd to contain the value of the
1.89      enami    1440:         * the file descriptor being sought for duplication. The error
1.28      mycroft  1441:         * return ensures that the vnode for this device will be released
                   1442:         * by vn_open. Open will detect this special error and take the
                   1443:         * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
                   1444:         * will simply report the error.
                   1445:         */
1.112     jdolecek 1446:        curlwp->l_dupfd = minor(dev);   /* XXX */
1.28      mycroft  1447:        return (ENODEV);
1.27      mycroft  1448: }
                   1449:
1.28      mycroft  1450: /*
                   1451:  * Duplicate the specified descriptor to a free descriptor.
1.118     yamt     1452:  *
                   1453:  * 'indx' has been fdalloc'ed (and will be fdremove'ed on error) by the caller.
1.28      mycroft  1454:  */
1.27      mycroft  1455: int
1.110     fvdl     1456: dupfdopen(struct proc *p, int indx, int dfd, int mode, int error)
1.72      lukem    1457: {
1.110     fvdl     1458:        struct filedesc *fdp;
1.118     yamt     1459:        struct file     *wfp;
1.27      mycroft  1460:
1.72      lukem    1461:        fdp = p->p_fd;
1.118     yamt     1462:
                   1463:        /* should be cleared by the caller */
                   1464:        KASSERT(fdp->fd_ofiles[indx] == NULL);
                   1465:
1.27      mycroft  1466:        /*
                   1467:         * If the to-be-dup'd fd number is greater than the allowed number
                   1468:         * of file descriptors, or the fd to be dup'd has already been
1.118     yamt     1469:         * closed, reject.
1.27      mycroft  1470:         */
1.77      thorpej  1471:
1.118     yamt     1472:        /*
                   1473:         * Note, in the case of indx == dfd, fd_getfile below returns NULL.
                   1474:         */
1.77      thorpej  1475:        if ((wfp = fd_getfile(fdp, dfd)) == NULL)
                   1476:                return (EBADF);
                   1477:
1.59      thorpej  1478:        FILE_USE(wfp);
                   1479:
1.27      mycroft  1480:        /*
1.28      mycroft  1481:         * There are two cases of interest here.
                   1482:         *
                   1483:         * For ENODEV simply dup (dfd) to file descriptor
                   1484:         * (indx) and return.
                   1485:         *
                   1486:         * For ENXIO steal away the file structure from (dfd) and
                   1487:         * store it in (indx).  (dfd) is effectively closed by
                   1488:         * this operation.
                   1489:         *
                   1490:         * Any other error code is just returned.
1.27      mycroft  1491:         */
1.28      mycroft  1492:        switch (error) {
                   1493:        case ENODEV:
                   1494:                /*
                   1495:                 * Check that the mode the file is being opened for is a
                   1496:                 * subset of the mode of the existing descriptor.
                   1497:                 */
1.59      thorpej  1498:                if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
1.110     fvdl     1499:                        FILE_UNUSE(wfp, p);
1.28      mycroft  1500:                        return (EACCES);
1.59      thorpej  1501:                }
1.28      mycroft  1502:                fdp->fd_ofiles[indx] = wfp;
                   1503:                fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
                   1504:                wfp->f_count++;
1.119     yamt     1505:                /* 'indx' has been fd_used'ed by caller */
1.110     fvdl     1506:                FILE_UNUSE(wfp, p);
1.28      mycroft  1507:                return (0);
1.27      mycroft  1508:
1.28      mycroft  1509:        case ENXIO:
                   1510:                /*
                   1511:                 * Steal away the file pointer from dfd, and stuff it into indx.
                   1512:                 */
                   1513:                fdp->fd_ofiles[indx] = fdp->fd_ofiles[dfd];
                   1514:                fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
                   1515:                fdp->fd_ofiles[dfd] = NULL;
                   1516:                fdp->fd_ofileflags[dfd] = 0;
                   1517:                /*
                   1518:                 * Complete the clean up of the filedesc structure by
                   1519:                 * recomputing the various hints.
                   1520:                 */
1.119     yamt     1521:                /* 'indx' has been fd_used'ed by caller */
1.28      mycroft  1522:                fd_unused(fdp, dfd);
1.110     fvdl     1523:                FILE_UNUSE(wfp, p);
1.28      mycroft  1524:                return (0);
1.16      cgd      1525:
1.28      mycroft  1526:        default:
1.110     fvdl     1527:                FILE_UNUSE(wfp, p);
1.28      mycroft  1528:                return (error);
                   1529:        }
                   1530:        /* NOTREACHED */
1.61      wrstuden 1531: }
                   1532:
                   1533: /*
                   1534:  * fcntl call which is being passed to the file's fs.
                   1535:  */
                   1536: int
1.110     fvdl     1537: fcntl_forfs(int fd, struct proc *p, int cmd, void *arg)
1.61      wrstuden 1538: {
1.72      lukem    1539:        struct file     *fp;
                   1540:        struct filedesc *fdp;
                   1541:        int             error;
                   1542:        u_int           size;
1.106     dsl      1543:        void            *data, *memp;
1.61      wrstuden 1544: #define STK_PARAMS     128
1.72      lukem    1545:        char            stkbuf[STK_PARAMS];
1.61      wrstuden 1546:
                   1547:        /* fd's value was validated in sys_fcntl before calling this routine */
                   1548:        fdp = p->p_fd;
                   1549:        fp = fdp->fd_ofiles[fd];
                   1550:
                   1551:        if ((fp->f_flag & (FREAD | FWRITE)) == 0)
                   1552:                return (EBADF);
                   1553:
                   1554:        /*
                   1555:         * Interpret high order word to find amount of data to be
                   1556:         * copied to/from the user's address space.
                   1557:         */
                   1558:        size = (size_t)F_PARAM_LEN(cmd);
                   1559:        if (size > F_PARAM_MAX)
                   1560:                return (EINVAL);
                   1561:        memp = NULL;
                   1562:        if (size > sizeof(stkbuf)) {
1.106     dsl      1563:                memp = malloc((u_long)size, M_IOCTLOPS, M_WAITOK);
1.61      wrstuden 1564:                data = memp;
                   1565:        } else
                   1566:                data = stkbuf;
                   1567:        if (cmd & F_FSIN) {
                   1568:                if (size) {
                   1569:                        error = copyin(arg, data, size);
                   1570:                        if (error) {
                   1571:                                if (memp)
                   1572:                                        free(memp, M_IOCTLOPS);
                   1573:                                return (error);
                   1574:                        }
                   1575:                } else
1.106     dsl      1576:                        *(void **)data = arg;
1.61      wrstuden 1577:        } else if ((cmd & F_FSOUT) && size)
                   1578:                /*
                   1579:                 * Zero the buffer so the user always
                   1580:                 * gets back something deterministic.
                   1581:                 */
                   1582:                memset(data, 0, size);
                   1583:        else if (cmd & F_FSVOID)
1.106     dsl      1584:                *(void **)data = arg;
1.61      wrstuden 1585:
                   1586:
1.110     fvdl     1587:        error = (*fp->f_ops->fo_fcntl)(fp, cmd, data, p);
1.61      wrstuden 1588:
                   1589:        /*
                   1590:         * Copy any data to user, size was
                   1591:         * already set and checked above.
                   1592:         */
                   1593:        if (error == 0 && (cmd & F_FSOUT) && size)
                   1594:                error = copyout(data, arg, size);
                   1595:        if (memp)
                   1596:                free(memp, M_IOCTLOPS);
                   1597:        return (error);
1.27      mycroft  1598: }
1.16      cgd      1599:
1.27      mycroft  1600: /*
                   1601:  * Close any files on exec?
                   1602:  */
                   1603: void
1.110     fvdl     1604: fdcloseexec(struct proc *p)
1.27      mycroft  1605: {
1.110     fvdl     1606:        struct filedesc *fdp;
1.72      lukem    1607:        int             fd;
1.80      thorpej  1608:
1.110     fvdl     1609:        fdunshare(p);
1.80      thorpej  1610:        cwdunshare(p);
1.16      cgd      1611:
1.72      lukem    1612:        fdp = p->p_fd;
1.27      mycroft  1613:        for (fd = 0; fd <= fdp->fd_lastfile; fd++)
                   1614:                if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
1.110     fvdl     1615:                        (void) fdrelease(p, fd);
1.86      christos 1616: }
                   1617:
                   1618: /*
                   1619:  * It is unsafe for set[ug]id processes to be started with file
                   1620:  * descriptors 0..2 closed, as these descriptors are given implicit
                   1621:  * significance in the Standard C library.  fdcheckstd() will create a
                   1622:  * descriptor referencing /dev/null for each of stdin, stdout, and
                   1623:  * stderr that is not already open.
                   1624:  */
1.92      atatat   1625: #define CHECK_UPTO 3
1.86      christos 1626: int
1.110     fvdl     1627: fdcheckstd(p)
                   1628:        struct proc *p;
1.109     darrenr  1629: {
1.86      christos 1630:        struct nameidata nd;
                   1631:        struct filedesc *fdp;
                   1632:        struct file *fp;
1.97      scw      1633:        struct file *devnullfp = NULL;  /* Quell compiler warning */
1.91      enami    1634:        struct proc *pp;
1.86      christos 1635:        register_t retval;
1.92      atatat   1636:        int fd, i, error, flags = FREAD|FWRITE, devnull = -1;
                   1637:        char closed[CHECK_UPTO * 3 + 1], which[3 + 1];
1.86      christos 1638:
1.92      atatat   1639:        closed[0] = '\0';
1.86      christos 1640:        if ((fdp = p->p_fd) == NULL)
1.89      enami    1641:                return (0);
1.92      atatat   1642:        for (i = 0; i < CHECK_UPTO; i++) {
1.86      christos 1643:                if (fdp->fd_ofiles[i] != NULL)
                   1644:                        continue;
1.92      atatat   1645:                snprintf(which, sizeof(which), ",%d", i);
1.108     itojun   1646:                strlcat(closed, which, sizeof(closed));
1.86      christos 1647:                if (devnull < 0) {
                   1648:                        if ((error = falloc(p, &fp, &fd)) != 0)
1.89      enami    1649:                                return (error);
1.86      christos 1650:                        NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, "/dev/null",
1.110     fvdl     1651:                            p);
1.86      christos 1652:                        if ((error = vn_open(&nd, flags, 0)) != 0) {
1.110     fvdl     1653:                                FILE_UNUSE(fp, p);
1.86      christos 1654:                                ffree(fp);
                   1655:                                fdremove(p->p_fd, fd);
1.89      enami    1656:                                return (error);
1.86      christos 1657:                        }
1.106     dsl      1658:                        fp->f_data = nd.ni_vp;
1.86      christos 1659:                        fp->f_flag = flags;
                   1660:                        fp->f_ops = &vnops;
                   1661:                        fp->f_type = DTYPE_VNODE;
                   1662:                        VOP_UNLOCK(nd.ni_vp, 0);
                   1663:                        devnull = fd;
1.88      christos 1664:                        devnullfp = fp;
1.87      christos 1665:                        FILE_SET_MATURE(fp);
1.86      christos 1666:                } else {
                   1667: restart:
                   1668:                        if ((error = fdalloc(p, 0, &fd)) != 0) {
                   1669:                                if (error == ENOSPC) {
                   1670:                                        fdexpand(p);
                   1671:                                        goto restart;
                   1672:                                }
1.89      enami    1673:                                return (error);
1.86      christos 1674:                        }
1.88      christos 1675:
1.104     yamt     1676:                        simple_lock(&devnullfp->f_slock);
1.88      christos 1677:                        FILE_USE(devnullfp);
                   1678:                        /* finishdup() will unuse the descriptors for us */
1.110     fvdl     1679:                        if ((error = finishdup(p, devnull, fd, &retval)) != 0)
1.89      enami    1680:                                return (error);
1.86      christos 1681:                }
                   1682:        }
1.104     yamt     1683:        if (devnullfp)
1.110     fvdl     1684:                FILE_UNUSE(devnullfp, p);
1.92      atatat   1685:        if (closed[0] != '\0') {
                   1686:                pp = p->p_pptr;
                   1687:                log(LOG_WARNING, "set{u,g}id pid %d (%s) "
                   1688:                    "was invoked by uid %d ppid %d (%s) "
                   1689:                    "with fd %s closed\n",
                   1690:                    p->p_pid, p->p_comm, pp->p_ucred->cr_uid,
                   1691:                    pp->p_pid, pp->p_comm, &closed[1]);
                   1692:        }
1.89      enami    1693:        return (0);
1.16      cgd      1694: }
1.92      atatat   1695: #undef CHECK_UPTO
1.113     jdolecek 1696:
                   1697: /*
                   1698:  * Sets descriptor owner. If the owner is a process, 'pgid'
                   1699:  * is set to positive value, process ID. If the owner is process group,
                   1700:  * 'pgid' is set to -pg_id.
                   1701:  */
                   1702: int
                   1703: fsetown(struct proc *p, pid_t *pgid, int cmd, const void *data)
                   1704: {
                   1705:        int id = *(int *)data;
                   1706:        int error;
                   1707:
                   1708:        switch (cmd) {
                   1709:        case TIOCSPGRP:
                   1710:                if (id < 0)
                   1711:                        return (EINVAL);
                   1712:                id = -id;
                   1713:                break;
                   1714:        default:
                   1715:                break;
                   1716:        }
                   1717:
                   1718:        if (id > 0 && !pfind(id))
                   1719:                return (ESRCH);
                   1720:        else if (id < 0 && (error = pgid_in_session(p, -id)))
                   1721:                return (error);
                   1722:
                   1723:        *pgid = id;
                   1724:        return (0);
                   1725: }
                   1726:
                   1727: /*
                   1728:  * Return descriptor owner information. If the value is positive,
                   1729:  * it's process ID. If it's negative, it's process group ID and
                   1730:  * needs the sign removed before use.
                   1731:  */
                   1732: int
                   1733: fgetown(struct proc *p, pid_t pgid, int cmd, void *data)
                   1734: {
                   1735:        switch (cmd) {
                   1736:        case TIOCGPGRP:
                   1737:                *(int *)data = -pgid;
                   1738:                break;
                   1739:        default:
                   1740:                *(int *)data = pgid;
                   1741:                break;
                   1742:        }
                   1743:        return (0);
                   1744: }
                   1745:
                   1746: /*
                   1747:  * Send signal to descriptor owner, either process or process group.
                   1748:  */
                   1749: void
1.114     christos 1750: fownsignal(pid_t pgid, int signo, int code, int band, void *fdescdata)
1.113     jdolecek 1751: {
                   1752:        struct proc *p1;
                   1753:        ksiginfo_t ksi;
                   1754:
                   1755:        memset(&ksi, 0, sizeof(ksi));
1.114     christos 1756:        ksi.ksi_signo = signo;
1.113     jdolecek 1757:        ksi.ksi_code = code;
                   1758:        ksi.ksi_band = band;
                   1759:
                   1760:        if (pgid > 0 && (p1 = pfind(pgid)))
                   1761:                kpsignal(p1, &ksi, fdescdata);
                   1762:        else if (pgid < 0)
                   1763:                kgsignal(-pgid, &ksi, fdescdata);
                   1764: }

CVSweb <webmaster@jp.NetBSD.org>