Annotation of Net2/kern/kern_descrip.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986, 1989, 1991 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  * 3. All advertising materials mentioning features or use of this software
        !            14:  *    must display the following acknowledgement:
        !            15:  *     This product includes software developed by the University of
        !            16:  *     California, Berkeley and its contributors.
        !            17:  * 4. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  *
        !            33:  *     @(#)kern_descrip.c      7.28 (Berkeley) 6/25/91
        !            34:  */
        !            35: 
        !            36: #include "param.h"
        !            37: #include "systm.h"
        !            38: #include "filedesc.h"
        !            39: #include "kernel.h"
        !            40: #include "vnode.h"
        !            41: #include "proc.h"
        !            42: #include "file.h"
        !            43: #include "socket.h"
        !            44: #include "socketvar.h"
        !            45: #include "stat.h"
        !            46: #include "ioctl.h"
        !            47: #include "fcntl.h"
        !            48: #include "malloc.h"
        !            49: #include "syslog.h"
        !            50: #include "resourcevar.h"
        !            51: 
        !            52: /*
        !            53:  * Descriptor management.
        !            54:  */
        !            55: struct file *filehead; /* head of list of open files */
        !            56: int nfiles;            /* actual number of open files */
        !            57: 
        !            58: /*
        !            59:  * System calls on descriptors.
        !            60:  */
        !            61: /* ARGSUSED */
        !            62: getdtablesize(p, uap, retval)
        !            63:        struct proc *p;
        !            64:        struct args *uap;
        !            65:        int *retval;
        !            66: {
        !            67: 
        !            68:        *retval = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
        !            69:        return (0);
        !            70: }
        !            71: 
        !            72: /*
        !            73:  * Duplicate a file descriptor.
        !            74:  */
        !            75: /* ARGSUSED */
        !            76: dup(p, uap, retval)
        !            77:        struct proc *p;
        !            78:        struct args {
        !            79:                int     i;
        !            80:        } *uap;
        !            81:        int *retval;
        !            82: {
        !            83:        register struct filedesc *fdp = p->p_fd;
        !            84:        struct file *fp;
        !            85:        int fd, error;
        !            86: 
        !            87:        /*
        !            88:         * XXX Compatibility
        !            89:         */
        !            90:        if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); }
        !            91: 
        !            92:        if ((unsigned)uap->i >= fdp->fd_nfiles ||
        !            93:            (fp = fdp->fd_ofiles[uap->i]) == NULL)
        !            94:                return (EBADF);
        !            95:        if (error = fdalloc(p, 0, &fd))
        !            96:                return (error);
        !            97:        fdp->fd_ofiles[fd] = fp;
        !            98:        fdp->fd_ofileflags[fd] = fdp->fd_ofileflags[uap->i] &~ UF_EXCLOSE;
        !            99:        fp->f_count++;
        !           100:        if (fd > fdp->fd_lastfile)
        !           101:                fdp->fd_lastfile = fd;
        !           102:        *retval = fd;
        !           103:        return (0);
        !           104: }
        !           105: 
        !           106: /*
        !           107:  * Duplicate a file descriptor to a particular value.
        !           108:  */
        !           109: /* ARGSUSED */
        !           110: dup2(p, uap, retval)
        !           111:        struct proc *p;
        !           112:        struct args {
        !           113:                u_int   from;
        !           114:                u_int   to;
        !           115:        } *uap;
        !           116:        int *retval;
        !           117: {
        !           118:        register struct filedesc *fdp = p->p_fd;
        !           119:        register struct file *fp;
        !           120:        register u_int old = uap->from, new = uap->to;
        !           121:        int i, error;
        !           122: 
        !           123:        if (old >= fdp->fd_nfiles ||
        !           124:            (fp = fdp->fd_ofiles[old]) == NULL ||
        !           125:            new >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
        !           126:                return (EBADF);
        !           127:        *retval = new;
        !           128:        if (old == new)
        !           129:                return (0);
        !           130:        if (new >= fdp->fd_nfiles) {
        !           131:                if (error = fdalloc(p, new, &i))
        !           132:                        return (error);
        !           133:                if (new != i)
        !           134:                        panic("dup2: fdalloc");
        !           135:        } else if (fdp->fd_ofiles[new]) {
        !           136:                if (fdp->fd_ofileflags[new] & UF_MAPPED)
        !           137:                        (void) munmapfd(p, new);
        !           138:                /*
        !           139:                 * dup2() must succeed even if the close has an error.
        !           140:                 */
        !           141:                (void) closef(fdp->fd_ofiles[new], p);
        !           142:        }
        !           143:        fdp->fd_ofiles[new] = fp;
        !           144:        fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] &~ UF_EXCLOSE;
        !           145:        fp->f_count++;
        !           146:        if (new > fdp->fd_lastfile)
        !           147:                fdp->fd_lastfile = new;
        !           148:        return (0);
        !           149: }
        !           150: 
        !           151: /*
        !           152:  * The file control system call.
        !           153:  */
        !           154: /* ARGSUSED */
        !           155: fcntl(p, uap, retval)
        !           156:        struct proc *p;
        !           157:        register struct args {
        !           158:                int     fd;
        !           159:                int     cmd;
        !           160:                int     arg;
        !           161:        } *uap;
        !           162:        int *retval;
        !           163: {
        !           164:        register struct filedesc *fdp = p->p_fd;
        !           165:        register struct file *fp;
        !           166:        register char *pop;
        !           167:        struct vnode *vp;
        !           168:        int i, tmp, error, flg = F_POSIX;
        !           169:        struct flock fl;
        !           170: 
        !           171:        if ((unsigned)uap->fd >= fdp->fd_nfiles ||
        !           172:            (fp = fdp->fd_ofiles[uap->fd]) == NULL)
        !           173:                return (EBADF);
        !           174:        pop = &fdp->fd_ofileflags[uap->fd];
        !           175:        switch(uap->cmd) {
        !           176:        case F_DUPFD:
        !           177:                if ((unsigned)uap->arg >= p->p_rlimit[RLIMIT_OFILE].rlim_cur)
        !           178:                        return (EINVAL);
        !           179:                if (error = fdalloc(p, uap->arg, &i))
        !           180:                        return (error);
        !           181:                fdp->fd_ofiles[i] = fp;
        !           182:                fdp->fd_ofileflags[i] = *pop &~ UF_EXCLOSE;
        !           183:                fp->f_count++;
        !           184:                if (i > fdp->fd_lastfile)
        !           185:                        fdp->fd_lastfile = i;
        !           186:                *retval = i;
        !           187:                return (0);
        !           188: 
        !           189:        case F_GETFD:
        !           190:                *retval = *pop & 1;
        !           191:                return (0);
        !           192: 
        !           193:        case F_SETFD:
        !           194:                *pop = (*pop &~ 1) | (uap->arg & 1);
        !           195:                return (0);
        !           196: 
        !           197:        case F_GETFL:
        !           198:                *retval = OFLAGS(fp->f_flag);
        !           199:                return (0);
        !           200: 
        !           201:        case F_SETFL:
        !           202:                fp->f_flag &= ~FCNTLFLAGS;
        !           203:                fp->f_flag |= FFLAGS(uap->arg) & FCNTLFLAGS;
        !           204:                tmp = fp->f_flag & FNONBLOCK;
        !           205:                error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
        !           206:                if (error)
        !           207:                        return (error);
        !           208:                tmp = fp->f_flag & FASYNC;
        !           209:                error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p);
        !           210:                if (!error)
        !           211:                        return (0);
        !           212:                fp->f_flag &= ~FNONBLOCK;
        !           213:                tmp = 0;
        !           214:                (void) (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p);
        !           215:                return (error);
        !           216: 
        !           217:        case F_GETOWN:
        !           218:                if (fp->f_type == DTYPE_SOCKET) {
        !           219:                        *retval = ((struct socket *)fp->f_data)->so_pgid;
        !           220:                        return (0);
        !           221:                }
        !           222:                error = (*fp->f_ops->fo_ioctl)
        !           223:                        (fp, (int)TIOCGPGRP, (caddr_t)retval, p);
        !           224:                *retval = -*retval;
        !           225:                return (error);
        !           226: 
        !           227:        case F_SETOWN:
        !           228:                if (fp->f_type == DTYPE_SOCKET) {
        !           229:                        ((struct socket *)fp->f_data)->so_pgid = uap->arg;
        !           230:                        return (0);
        !           231:                }
        !           232:                if (uap->arg <= 0) {
        !           233:                        uap->arg = -uap->arg;
        !           234:                } else {
        !           235:                        struct proc *p1 = pfind(uap->arg);
        !           236:                        if (p1 == 0)
        !           237:                                return (ESRCH);
        !           238:                        uap->arg = p1->p_pgrp->pg_id;
        !           239:                }
        !           240:                return ((*fp->f_ops->fo_ioctl)
        !           241:                        (fp, (int)TIOCSPGRP, (caddr_t)&uap->arg, p));
        !           242: 
        !           243:        case F_SETLKW:
        !           244:                flg |= F_WAIT;
        !           245:                /* Fall into F_SETLK */
        !           246: 
        !           247:        case F_SETLK:
        !           248:                if (fp->f_type != DTYPE_VNODE)
        !           249:                        return (EBADF);
        !           250:                vp = (struct vnode *)fp->f_data;
        !           251:                /* Copy in the lock structure */
        !           252:                error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
        !           253:                if (error)
        !           254:                        return (error);
        !           255:                if (fl.l_whence == SEEK_CUR)
        !           256:                        fl.l_start += fp->f_offset;
        !           257:                switch (fl.l_type) {
        !           258: 
        !           259:                case F_RDLCK:
        !           260:                        if ((fp->f_flag & FREAD) == 0)
        !           261:                                return (EBADF);
        !           262:                        p->p_flag |= SADVLCK;
        !           263:                        return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
        !           264: 
        !           265:                case F_WRLCK:
        !           266:                        if ((fp->f_flag & FWRITE) == 0)
        !           267:                                return (EBADF);
        !           268:                        p->p_flag |= SADVLCK;
        !           269:                        return (VOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg));
        !           270: 
        !           271:                case F_UNLCK:
        !           272:                        return (VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
        !           273:                                F_POSIX));
        !           274: 
        !           275:                default:
        !           276:                        return (EINVAL);
        !           277:                }
        !           278: 
        !           279:        case F_GETLK:
        !           280:                if (fp->f_type != DTYPE_VNODE)
        !           281:                        return (EBADF);
        !           282:                vp = (struct vnode *)fp->f_data;
        !           283:                /* Copy in the lock structure */
        !           284:                error = copyin((caddr_t)uap->arg, (caddr_t)&fl, sizeof (fl));
        !           285:                if (error)
        !           286:                        return (error);
        !           287:                if (fl.l_whence == SEEK_CUR)
        !           288:                        fl.l_start += fp->f_offset;
        !           289:                if (error = VOP_ADVLOCK(vp, (caddr_t)p, F_GETLK, &fl, F_POSIX))
        !           290:                        return (error);
        !           291:                return (copyout((caddr_t)&fl, (caddr_t)uap->arg, sizeof (fl)));
        !           292: 
        !           293:        default:
        !           294:                return (EINVAL);
        !           295:        }
        !           296:        /* NOTREACHED */
        !           297: }
        !           298: 
        !           299: /*
        !           300:  * Close a file descriptor.
        !           301:  */
        !           302: /* ARGSUSED */
        !           303: close(p, uap, retval)
        !           304:        struct proc *p;
        !           305:        struct args {
        !           306:                int     fd;
        !           307:        } *uap;
        !           308:        int *retval;
        !           309: {
        !           310:        register struct filedesc *fdp = p->p_fd;
        !           311:        register struct file *fp;
        !           312:        register int fd = uap->fd;
        !           313:        register u_char *pf;
        !           314: 
        !           315:        if ((unsigned)fd >= fdp->fd_nfiles ||
        !           316:            (fp = fdp->fd_ofiles[fd]) == NULL)
        !           317:                return (EBADF);
        !           318:        pf = (u_char *)&fdp->fd_ofileflags[fd];
        !           319:        if (*pf & UF_MAPPED)
        !           320:                (void) munmapfd(p, fd);
        !           321:        fdp->fd_ofiles[fd] = NULL;
        !           322:        while (fdp->fd_lastfile > 0 && fdp->fd_ofiles[fdp->fd_lastfile] == NULL)
        !           323:                fdp->fd_lastfile--;
        !           324:        if (fd < fdp->fd_freefile)
        !           325:                fdp->fd_freefile = fd;
        !           326:        *pf = 0;
        !           327:        return (closef(fp, p));
        !           328: }
        !           329: 
        !           330: /*
        !           331:  * Return status information about a file descriptor.
        !           332:  */
        !           333: /* ARGSUSED */
        !           334: fstat(p, uap, retval)
        !           335:        struct proc *p;
        !           336:        register struct args {
        !           337:                int     fd;
        !           338:                struct  stat *sb;
        !           339:        } *uap;
        !           340:        int *retval;
        !           341: {
        !           342:        register struct filedesc *fdp = p->p_fd;
        !           343:        register struct file *fp;
        !           344:        struct stat ub;
        !           345:        int error;
        !           346: 
        !           347:        if ((unsigned)uap->fd >= fdp->fd_nfiles ||
        !           348:            (fp = fdp->fd_ofiles[uap->fd]) == NULL)
        !           349:                return (EBADF);
        !           350:        switch (fp->f_type) {
        !           351: 
        !           352:        case DTYPE_VNODE:
        !           353:                error = vn_stat((struct vnode *)fp->f_data, &ub, p);
        !           354:                break;
        !           355: 
        !           356:        case DTYPE_SOCKET:
        !           357:                error = soo_stat((struct socket *)fp->f_data, &ub);
        !           358:                break;
        !           359: 
        !           360:        default:
        !           361:                panic("fstat");
        !           362:                /*NOTREACHED*/
        !           363:        }
        !           364:        if (error == 0)
        !           365:                error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
        !           366:        return (error);
        !           367: }
        !           368: 
        !           369: /*
        !           370:  * Allocate a file descriptor for the process.
        !           371:  */
        !           372: int fdexpand;
        !           373: 
        !           374: fdalloc(p, want, result)
        !           375:        struct proc *p;
        !           376:        int want;
        !           377:        int *result;
        !           378: {
        !           379:        register struct filedesc *fdp = p->p_fd;
        !           380:        register int i;
        !           381:        int lim, last, nfiles;
        !           382:        struct file **newofile;
        !           383:        char *newofileflags;
        !           384: 
        !           385:        /*
        !           386:         * Search for a free descriptor starting at the higher
        !           387:         * of want or fd_freefile.  If that fails, consider
        !           388:         * expanding the ofile array.
        !           389:         */
        !           390:        lim = p->p_rlimit[RLIMIT_OFILE].rlim_cur;
        !           391:        for (;;) {
        !           392:                last = min(fdp->fd_nfiles, lim);
        !           393:                if ((i = want) < fdp->fd_freefile)
        !           394:                        i = fdp->fd_freefile;
        !           395:                for (; i < last; i++) {
        !           396:                        if (fdp->fd_ofiles[i] == NULL) {
        !           397:                                fdp->fd_ofileflags[i] = 0;
        !           398:                                if (i > fdp->fd_lastfile)
        !           399:                                        fdp->fd_lastfile = i;
        !           400:                                if (want <= fdp->fd_freefile)
        !           401:                                        fdp->fd_freefile = i;
        !           402:                                *result = i;
        !           403:                                return (0);
        !           404:                        }
        !           405:                }
        !           406: 
        !           407:                /*
        !           408:                 * No space in current array.  Expand?
        !           409:                 */
        !           410:                if (fdp->fd_nfiles >= lim)
        !           411:                        return (EMFILE);
        !           412:                if (fdp->fd_nfiles < NDEXTENT)
        !           413:                        nfiles = NDEXTENT;
        !           414:                else
        !           415:                        nfiles = 2 * fdp->fd_nfiles;
        !           416:                MALLOC(newofile, struct file **, nfiles * OFILESIZE,
        !           417:                    M_FILEDESC, M_WAITOK);
        !           418:                newofileflags = (char *) &newofile[nfiles];
        !           419:                /*
        !           420:                 * Copy the existing ofile and ofileflags arrays
        !           421:                 * and zero the new portion of each array.
        !           422:                 */
        !           423:                bcopy(fdp->fd_ofiles, newofile,
        !           424:                        (i = sizeof(struct file *) * fdp->fd_nfiles));
        !           425:                bzero((char *)newofile + i, nfiles * sizeof(struct file *) - i);
        !           426:                bcopy(fdp->fd_ofileflags, newofileflags,
        !           427:                        (i = sizeof(char) * fdp->fd_nfiles));
        !           428:                bzero(newofileflags + i, nfiles * sizeof(char) - i);
        !           429:                if (fdp->fd_nfiles > NDFILE)
        !           430:                        FREE(fdp->fd_ofiles, M_FILEDESC);
        !           431:                fdp->fd_ofiles = newofile;
        !           432:                fdp->fd_ofileflags = newofileflags;
        !           433:                fdp->fd_nfiles = nfiles;
        !           434:                fdexpand++;
        !           435:        }
        !           436: }
        !           437: 
        !           438: /*
        !           439:  * Check to see whether n user file descriptors
        !           440:  * are available to the process p.
        !           441:  */
        !           442: fdavail(p, n)
        !           443:        struct proc *p;
        !           444:        register int n;
        !           445: {
        !           446:        register struct filedesc *fdp = p->p_fd;
        !           447:        register struct file **fpp;
        !           448:        register int i;
        !           449: 
        !           450:        if ((i = p->p_rlimit[RLIMIT_OFILE].rlim_cur - fdp->fd_nfiles) > 0 &&
        !           451:            (n -= i) <= 0)
        !           452:                return (1);
        !           453:        fpp = &fdp->fd_ofiles[fdp->fd_freefile];
        !           454:        for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++)
        !           455:                if (*fpp == NULL && --n <= 0)
        !           456:                        return (1);
        !           457:        return (0);
        !           458: }
        !           459: 
        !           460: /*
        !           461:  * Create a new open file structure and allocate
        !           462:  * a file decriptor for the process that refers to it.
        !           463:  */
        !           464: falloc(p, resultfp, resultfd)
        !           465:        register struct proc *p;
        !           466:        struct file **resultfp;
        !           467:        int *resultfd;
        !           468: {
        !           469:        register struct file *fp, *fq, **fpp;
        !           470:        int error, i;
        !           471: 
        !           472:        if (error = fdalloc(p, 0, &i))
        !           473:                return (error);
        !           474:        if (nfiles >= maxfiles) {
        !           475:                tablefull("file");
        !           476:                return (ENFILE);
        !           477:        }
        !           478:        /*
        !           479:         * Allocate a new file descriptor.
        !           480:         * If the process has file descriptor zero open, add to the list
        !           481:         * of open files at that point, otherwise put it at the front of
        !           482:         * the list of open files.
        !           483:         */
        !           484:        nfiles++;
        !           485:        MALLOC(fp, struct file *, sizeof(struct file), M_FILE, M_WAITOK);
        !           486:        if (fq = p->p_fd->fd_ofiles[0])
        !           487:                fpp = &fq->f_filef;
        !           488:        else
        !           489:                fpp = &filehead;
        !           490:        p->p_fd->fd_ofiles[i] = fp;
        !           491:        if (fq = *fpp)
        !           492:                fq->f_fileb = &fp->f_filef;
        !           493:        fp->f_filef = fq;
        !           494:        fp->f_fileb = fpp;
        !           495:        *fpp = fp;
        !           496:        fp->f_count = 1;
        !           497:        fp->f_msgcount = 0;
        !           498:        fp->f_offset = 0;
        !           499:        fp->f_cred = p->p_ucred;
        !           500:        crhold(fp->f_cred);
        !           501:        if (resultfp)
        !           502:                *resultfp = fp;
        !           503:        if (resultfd)
        !           504:                *resultfd = i;
        !           505:        return (0);
        !           506: }
        !           507: 
        !           508: /*
        !           509:  * Free a file descriptor.
        !           510:  */
        !           511: ffree(fp)
        !           512:        register struct file *fp;
        !           513: {
        !           514:        register struct file *fq;
        !           515: 
        !           516:        if (fq = fp->f_filef)
        !           517:                fq->f_fileb = fp->f_fileb;
        !           518:        *fp->f_fileb = fq;
        !           519:        crfree(fp->f_cred);
        !           520: #ifdef DIAGNOSTIC
        !           521:        fp->f_filef = NULL;
        !           522:        fp->f_fileb = NULL;
        !           523:        fp->f_count = 0;
        !           524: #endif
        !           525:        nfiles--;
        !           526:        FREE(fp, M_FILE);
        !           527: }
        !           528: 
        !           529: /*
        !           530:  * Copy a filedesc structure.
        !           531:  */
        !           532: struct filedesc *
        !           533: fdcopy(p)
        !           534:        struct proc *p;
        !           535: {
        !           536:        register struct filedesc *newfdp, *fdp = p->p_fd;
        !           537:        register struct file **fpp;
        !           538:        register int i;
        !           539: 
        !           540:        MALLOC(newfdp, struct filedesc *, sizeof(struct filedesc0),
        !           541:            M_FILEDESC, M_WAITOK);
        !           542:        bcopy(fdp, newfdp, sizeof(struct filedesc));
        !           543:        VREF(newfdp->fd_cdir);
        !           544:        if (newfdp->fd_rdir)
        !           545:                VREF(newfdp->fd_rdir);
        !           546:        newfdp->fd_refcnt = 1;
        !           547: 
        !           548:        /*
        !           549:         * If the number of open files fits in the internal arrays
        !           550:         * of the open file structure, use them, otherwise allocate
        !           551:         * additional memory for the number of descriptors currently
        !           552:         * in use.
        !           553:         */
        !           554:        if (newfdp->fd_lastfile < NDFILE) {
        !           555:                newfdp->fd_ofiles = ((struct filedesc0 *) newfdp)->fd_dfiles;
        !           556:                newfdp->fd_ofileflags =
        !           557:                    ((struct filedesc0 *) newfdp)->fd_dfileflags;
        !           558:                i = NDFILE;
        !           559:        } else {
        !           560:                /*
        !           561:                 * Compute the smallest multiple of NDEXTENT needed
        !           562:                 * for the file descriptors currently in use,
        !           563:                 * allowing the table to shrink.
        !           564:                 */
        !           565:                i = newfdp->fd_nfiles;
        !           566:                while (i > 2 * NDEXTENT && i >= newfdp->fd_lastfile * 2)
        !           567:                        i /= 2;
        !           568:                MALLOC(newfdp->fd_ofiles, struct file **, i * OFILESIZE,
        !           569:                    M_FILEDESC, M_WAITOK);
        !           570:                newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
        !           571:        }
        !           572:        newfdp->fd_nfiles = i;
        !           573:        bcopy(fdp->fd_ofiles, newfdp->fd_ofiles, i * sizeof(struct file **));
        !           574:        bcopy(fdp->fd_ofileflags, newfdp->fd_ofileflags, i * sizeof(char));
        !           575:        fpp = newfdp->fd_ofiles;
        !           576:        for (i = newfdp->fd_lastfile; i-- >= 0; fpp++)
        !           577:                if (*fpp != NULL)
        !           578:                        (*fpp)->f_count++;
        !           579:        return (newfdp);
        !           580: }
        !           581: 
        !           582: /*
        !           583:  * Release a filedesc structure.
        !           584:  */
        !           585: void
        !           586: fdfree(p)
        !           587:        struct proc *p;
        !           588: {
        !           589:        register struct filedesc *fdp = p->p_fd;
        !           590:        struct file **fpp;
        !           591:        register int i;
        !           592: 
        !           593:        if (--fdp->fd_refcnt > 0)
        !           594:                return;
        !           595:        fpp = fdp->fd_ofiles;
        !           596:        for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
        !           597:                if (*fpp)
        !           598:                        (void) closef(*fpp, p);
        !           599:        if (fdp->fd_nfiles > NDFILE)
        !           600:                FREE(fdp->fd_ofiles, M_FILEDESC);
        !           601:        vrele(fdp->fd_cdir);
        !           602:        if (fdp->fd_rdir)
        !           603:                vrele(fdp->fd_rdir);
        !           604:        FREE(fdp, M_FILEDESC);
        !           605: }
        !           606: 
        !           607: /*
        !           608:  * Internal form of close.
        !           609:  * Decrement reference count on file structure.
        !           610:  */
        !           611: closef(fp, p)
        !           612:        register struct file *fp;
        !           613:        register struct proc *p;
        !           614: {
        !           615:        struct vnode *vp;
        !           616:        struct flock lf;
        !           617:        int error;
        !           618: 
        !           619:        if (fp == NULL)
        !           620:                return (0);
        !           621:        /*
        !           622:         * POSIX record locking dictates that any close releases ALL
        !           623:         * locks owned by this process.  This is handled by setting
        !           624:         * a flag in the unlock to free ONLY locks obeying POSIX
        !           625:         * semantics, and not to free BSD-style file locks.
        !           626:         */
        !           627:        if ((p->p_flag & SADVLCK) && fp->f_type == DTYPE_VNODE) {
        !           628:                lf.l_whence = SEEK_SET;
        !           629:                lf.l_start = 0;
        !           630:                lf.l_len = 0;
        !           631:                lf.l_type = F_UNLCK;
        !           632:                vp = (struct vnode *)fp->f_data;
        !           633:                (void) VOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX);
        !           634:        }
        !           635:        if (--fp->f_count > 0)
        !           636:                return (0);
        !           637:        if (fp->f_count < 0)
        !           638:                panic("closef: count < 0");
        !           639:        if ((fp->f_flag & FHASLOCK) && fp->f_type == DTYPE_VNODE) {
        !           640:                lf.l_whence = SEEK_SET;
        !           641:                lf.l_start = 0;
        !           642:                lf.l_len = 0;
        !           643:                lf.l_type = F_UNLCK;
        !           644:                vp = (struct vnode *)fp->f_data;
        !           645:                (void) VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK);
        !           646:        }
        !           647:        error = (*fp->f_ops->fo_close)(fp, p);
        !           648:        ffree(fp);
        !           649:        return (error);
        !           650: }
        !           651: 
        !           652: /*
        !           653:  * Apply an advisory lock on a file descriptor.
        !           654:  *
        !           655:  * Just attempt to get a record lock of the requested type on
        !           656:  * the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
        !           657:  */
        !           658: 
        !           659: /* ARGSUSED */
        !           660: flock(p, uap, retval)
        !           661:        struct proc *p;
        !           662:        register struct args {
        !           663:                int     fd;
        !           664:                int     how;
        !           665:        } *uap;
        !           666:        int *retval;
        !           667: {
        !           668:        register struct filedesc *fdp = p->p_fd;
        !           669:        register struct file *fp;
        !           670:        struct vnode *vp;
        !           671:        struct flock lf;
        !           672:        int error;
        !           673: 
        !           674:        if ((unsigned)uap->fd >= fdp->fd_nfiles ||
        !           675:            (fp = fdp->fd_ofiles[uap->fd]) == NULL)
        !           676:                return (EBADF);
        !           677:        if (fp->f_type != DTYPE_VNODE)
        !           678:                return (EOPNOTSUPP);
        !           679:        vp = (struct vnode *)fp->f_data;
        !           680:        lf.l_whence = SEEK_SET;
        !           681:        lf.l_start = 0;
        !           682:        lf.l_len = 0;
        !           683:        if (uap->how & LOCK_UN) {
        !           684:                lf.l_type = F_UNLCK;
        !           685:                fp->f_flag &= ~FHASLOCK;
        !           686:                return (VOP_ADVLOCK(vp, (caddr_t)fp, F_UNLCK, &lf, F_FLOCK));
        !           687:        }
        !           688:        if (uap->how & LOCK_EX)
        !           689:                lf.l_type = F_WRLCK;
        !           690:        else if (uap->how & LOCK_SH)
        !           691:                lf.l_type = F_RDLCK;
        !           692:        else
        !           693:                return (EBADF);
        !           694:        fp->f_flag |= FHASLOCK;
        !           695:        if (uap->how & LOCK_NB)
        !           696:                return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK));
        !           697:        return (VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, F_FLOCK|F_WAIT));
        !           698: }
        !           699: 
        !           700: /*
        !           701:  * File Descriptor pseudo-device driver (/dev/fd/).
        !           702:  *
        !           703:  * Opening minor device N dup()s the file (if any) connected to file
        !           704:  * descriptor N belonging to the calling process.  Note that this driver
        !           705:  * consists of only the ``open()'' routine, because all subsequent
        !           706:  * references to this file will be direct to the other driver.
        !           707:  */
        !           708: /* ARGSUSED */
        !           709: fdopen(dev, mode, type)
        !           710:        dev_t dev;
        !           711:        int mode, type;
        !           712: {
        !           713: 
        !           714:        /*
        !           715:         * XXX Kludge: set curproc->p_dupfd to contain the value of the
        !           716:         * the file descriptor being sought for duplication. The error 
        !           717:         * return ensures that the vnode for this device will be released
        !           718:         * by vn_open. Open will detect this special error and take the
        !           719:         * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
        !           720:         * will simply report the error.
        !           721:         */
        !           722:        curproc->p_dupfd = minor(dev);          /* XXX */
        !           723:        return (ENODEV);
        !           724: }
        !           725: 
        !           726: /*
        !           727:  * Duplicate the specified descriptor to a free descriptor.
        !           728:  */
        !           729: dupfdopen(fdp, indx, dfd, mode)
        !           730:        register struct filedesc *fdp;
        !           731:        register int indx, dfd;
        !           732:        int mode;
        !           733: {
        !           734:        register struct file *wfp;
        !           735:        struct file *fp;
        !           736:        
        !           737:        /*
        !           738:         * If the to-be-dup'd fd number is greater than the allowed number
        !           739:         * of file descriptors, or the fd to be dup'd has already been
        !           740:         * closed, reject.  Note, check for new == old is necessary as
        !           741:         * falloc could allocate an already closed to-be-dup'd descriptor
        !           742:         * as the new descriptor.
        !           743:         */
        !           744:        fp = fdp->fd_ofiles[indx];
        !           745:        if ((u_int)dfd >= fdp->fd_nfiles ||
        !           746:            (wfp = fdp->fd_ofiles[dfd]) == NULL || fp == wfp)
        !           747:                return (EBADF);
        !           748: 
        !           749:        /*
        !           750:         * Check that the mode the file is being opened for is a subset 
        !           751:         * of the mode of the existing descriptor.
        !           752:         */
        !           753:        if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
        !           754:                return (EACCES);
        !           755:        fdp->fd_ofiles[indx] = wfp;
        !           756:        fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd];
        !           757:        wfp->f_count++;
        !           758:        if (indx > fdp->fd_lastfile)
        !           759:                fdp->fd_lastfile = indx;
        !           760:        return (0);
        !           761: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.