Annotation of Net2/kern/kern_descrip.c, revision 1.1.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.