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

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

unix.superglobalmegacorp.com

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