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

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

unix.superglobalmegacorp.com

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