Annotation of 43BSDReno/sys/kern/kern_descrip.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution is only permitted until one year after the first shipment
                      6:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                      7:  * binary forms are permitted provided that: (1) source distributions retain
                      8:  * this entire copyright notice and comment, and (2) distributions including
                      9:  * binaries display the following acknowledgement:  This product includes
                     10:  * software developed by the University of California, Berkeley and its
                     11:  * contributors'' in the documentation or other materials provided with the
                     12:  * distribution and in all advertising materials mentioning features or use
                     13:  * of this software.  Neither the name of the University nor the names of
                     14:  * its contributors may be used to endorse or promote products derived from
                     15:  * this software without specific prior written permission.
                     16:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     17:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     18:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     19:  *
                     20:  *     @(#)kern_descrip.c      7.16 (Berkeley) 6/28/90
                     21:  */
                     22: 
                     23: #include "param.h"
                     24: #include "systm.h"
                     25: #include "user.h"
                     26: #include "kernel.h"
                     27: #include "vnode.h"
                     28: #include "proc.h"
                     29: #include "file.h"
                     30: #include "socket.h"
                     31: #include "socketvar.h"
                     32: #include "stat.h"
                     33: #include "ioctl.h"
                     34: 
                     35: /*
                     36:  * Descriptor management.
                     37:  */
                     38: 
                     39: /*
                     40:  * System calls on descriptors.
                     41:  */
                     42: /* ARGSUSED */
                     43: getdtablesize(p, uap, retval)
                     44:        struct proc *p;
                     45:        struct args *uap;
                     46:        int *retval;
                     47: {
                     48: 
                     49:        *retval = NOFILE;
                     50:        return (0);
                     51: }
                     52: 
                     53: /*
                     54:  * Duplicate a file descriptor.
                     55:  */
                     56: /* ARGSUSED */
                     57: dup(p, uap, retval)
                     58:        struct proc *p;
                     59:        struct args {
                     60:                int     i;
                     61:        } *uap;
                     62:        int *retval;
                     63: {
                     64:        struct file *fp;
                     65:        int fd, error;
                     66: 
                     67:        /*
                     68:         * XXX Compatibility
                     69:         */
                     70:        if (uap->i &~ 077) { uap->i &= 077; return (dup2(p, uap, retval)); }
                     71: 
                     72:        if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
                     73:                return (EBADF);
                     74:        if (error = ufalloc(0, &fd))
                     75:                return (error);
                     76:        u.u_ofile[fd] = fp;
                     77:        u.u_pofile[fd] = u.u_pofile[uap->i] &~ UF_EXCLOSE;
                     78:        fp->f_count++;
                     79:        if (fd > u.u_lastfile)
                     80:                u.u_lastfile = fd;
                     81:        *retval = fd;
                     82:        return (0);
                     83: }
                     84: 
                     85: /*
                     86:  * Duplicate a file descriptor to a particular value.
                     87:  */
                     88: /* ARGSUSED */
                     89: dup2(p, uap, retval)
                     90:        struct proc *p;
                     91:        register struct args {
                     92:                int     i;
                     93:                int     j;
                     94:        } *uap;
                     95:        int *retval;
                     96: {
                     97:        register struct file *fp;
                     98:        int error;
                     99: 
                    100:        if ((unsigned)uap->i >= NOFILE || (fp = u.u_ofile[uap->i]) == NULL)
                    101:                return (EBADF);
                    102:        if (uap->j < 0 || uap->j >= NOFILE)
                    103:                return (EBADF);
                    104:        *retval = uap->j;
                    105:        if (uap->i == uap->j)
                    106:                return (0);
                    107:        if (u.u_ofile[uap->j]) {
                    108:                if (u.u_pofile[uap->j] & UF_MAPPED)
                    109:                        munmapfd(uap->j);
                    110:                error = closef(u.u_ofile[uap->j]);
                    111:        }
                    112:        u.u_ofile[uap->j] = fp;
                    113:        u.u_pofile[uap->j] = u.u_pofile[uap->i] &~ UF_EXCLOSE;
                    114:        fp->f_count++;
                    115:        if (uap->j > u.u_lastfile)
                    116:                u.u_lastfile = uap->j;
                    117:        /*
                    118:         * dup2() must suceed even though the close had an error.
                    119:         */
                    120:        error = 0;              /* XXX */
                    121:        return (error);
                    122: }
                    123: 
                    124: /*
                    125:  * The file control system call.
                    126:  */
                    127: /* ARGSUSED */
                    128: fcntl(p, uap, retval)
                    129:        struct proc *p;
                    130:        register struct args {
                    131:                int     fdes;
                    132:                int     cmd;
                    133:                int     arg;
                    134:        } *uap;
                    135:        int *retval;
                    136: {
                    137:        register struct file *fp;
                    138:        register char *pop;
                    139:        int i, error;
                    140: 
                    141:        if ((unsigned)uap->fdes >= NOFILE ||
                    142:            (fp = u.u_ofile[uap->fdes]) == NULL)
                    143:                return (EBADF);
                    144:        pop = &u.u_pofile[uap->fdes];
                    145:        switch(uap->cmd) {
                    146:        case F_DUPFD:
                    147:                if (uap->arg < 0 || uap->arg >= NOFILE)
                    148:                        return (EINVAL);
                    149:                if (error = ufalloc(uap->arg, &i))
                    150:                        return (error);
                    151:                u.u_ofile[i] = fp;
                    152:                u.u_pofile[i] = *pop &~ UF_EXCLOSE;
                    153:                fp->f_count++;
                    154:                if (i > u.u_lastfile)
                    155:                        u.u_lastfile = i;
                    156:                *retval = i;
                    157:                return (0);
                    158: 
                    159:        case F_GETFD:
                    160:                *retval = *pop & 1;
                    161:                return (0);
                    162: 
                    163:        case F_SETFD:
                    164:                *pop = (*pop &~ 1) | (uap->arg & 1);
                    165:                return (0);
                    166: 
                    167:        case F_GETFL:
                    168:                *retval = fp->f_flag + FOPEN;
                    169:                return (0);
                    170: 
                    171:        case F_SETFL:
                    172:                fp->f_flag &= FCNTLCANT;
                    173:                fp->f_flag |= (uap->arg-FOPEN) &~ FCNTLCANT;
                    174:                if (error = fset(fp, FNDELAY, fp->f_flag & FNDELAY))
                    175:                        return (error);
                    176:                if (error = fset(fp, FASYNC, fp->f_flag & FASYNC))
                    177:                        (void) fset(fp, FNDELAY, 0);
                    178:                return (error);
                    179: 
                    180:        case F_GETOWN:
                    181:                return (fgetown(fp, retval));
                    182: 
                    183:        case F_SETOWN:
                    184:                return (fsetown(fp, uap->arg));
                    185: 
                    186:        default:
                    187:                return (EINVAL);
                    188:        }
                    189:        /* NOTREACHED */
                    190: }
                    191: 
                    192: fset(fp, bit, value)
                    193:        struct file *fp;
                    194:        int bit, value;
                    195: {
                    196: 
                    197:        if (value)
                    198:                fp->f_flag |= bit;
                    199:        else
                    200:                fp->f_flag &= ~bit;
                    201:        return (fioctl(fp, (int)(bit == FNDELAY ? FIONBIO : FIOASYNC),
                    202:            (caddr_t)&value));
                    203: }
                    204: 
                    205: fgetown(fp, valuep)
                    206:        struct file *fp;
                    207:        int *valuep;
                    208: {
                    209:        int error;
                    210: 
                    211:        switch (fp->f_type) {
                    212: 
                    213:        case DTYPE_SOCKET:
                    214:                *valuep = ((struct socket *)fp->f_data)->so_pgid;
                    215:                return (0);
                    216: 
                    217:        default:
                    218:                error = fioctl(fp, (int)TIOCGPGRP, (caddr_t)valuep);
                    219:                *valuep = -*valuep;
                    220:                return (error);
                    221:        }
                    222: }
                    223: 
                    224: fsetown(fp, value)
                    225:        struct file *fp;
                    226:        int value;
                    227: {
                    228: 
                    229:        if (fp->f_type == DTYPE_SOCKET) {
                    230:                ((struct socket *)fp->f_data)->so_pgid = value;
                    231:                return (0);
                    232:        }
                    233:        if (value > 0) {
                    234:                struct proc *p = pfind(value);
                    235:                if (p == 0)
                    236:                        return (ESRCH);
                    237:                value = p->p_pgrp->pg_id;
                    238:        } else
                    239:                value = -value;
                    240:        return (fioctl(fp, (int)TIOCSPGRP, (caddr_t)&value));
                    241: }
                    242: 
                    243: fioctl(fp, cmd, value)
                    244:        struct file *fp;
                    245:        int cmd;
                    246:        caddr_t value;
                    247: {
                    248: 
                    249:        return ((*fp->f_ops->fo_ioctl)(fp, cmd, value));
                    250: }
                    251: 
                    252: /*
                    253:  * Close a file descriptor.
                    254:  */
                    255: /* ARGSUSED */
                    256: close(p, uap, retval)
                    257:        struct proc *p;
                    258:        struct args {
                    259:                int     fdes;
                    260:        } *uap;
                    261:        int *retval;
                    262: {
                    263:        register struct file *fp;
                    264:        register u_char *pf;
                    265: 
                    266:        if ((unsigned)uap->fdes >= NOFILE ||
                    267:            (fp = u.u_ofile[uap->fdes]) == NULL)
                    268:                return (EBADF);
                    269:        pf = (u_char *)&u.u_pofile[uap->fdes];
                    270:        if (*pf & UF_MAPPED)
                    271:                munmapfd(uap->fdes);
                    272:        u.u_ofile[uap->fdes] = NULL;
                    273:        while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
                    274:                u.u_lastfile--;
                    275:        *pf = 0;
                    276:        return (closef(fp));
                    277: }
                    278: 
                    279: /*
                    280:  * Return status information about a file descriptor.
                    281:  */
                    282: /* ARGSUSED */
                    283: fstat(p, uap, retval)
                    284:        struct proc *p;
                    285:        register struct args {
                    286:                int     fdes;
                    287:                struct  stat *sb;
                    288:        } *uap;
                    289:        int *retval;
                    290: {
                    291:        register struct file *fp;
                    292:        struct stat ub;
                    293:        int error;
                    294: 
                    295:        if ((unsigned)uap->fdes >= NOFILE ||
                    296:            (fp = u.u_ofile[uap->fdes]) == NULL)
                    297:                return (EBADF);
                    298:        switch (fp->f_type) {
                    299: 
                    300:        case DTYPE_VNODE:
                    301:                error = vn_stat((struct vnode *)fp->f_data, &ub);
                    302:                break;
                    303: 
                    304:        case DTYPE_SOCKET:
                    305:                error = soo_stat((struct socket *)fp->f_data, &ub);
                    306:                break;
                    307: 
                    308:        default:
                    309:                panic("fstat");
                    310:                /*NOTREACHED*/
                    311:        }
                    312:        if (error == 0)
                    313:                error = copyout((caddr_t)&ub, (caddr_t)uap->sb, sizeof (ub));
                    314:        return (error);
                    315: }
                    316: 
                    317: /*
                    318:  * Allocate a user file descriptor.
                    319:  */
                    320: ufalloc(want, result)
                    321:        register int want;
                    322:        int *result;
                    323: {
                    324: 
                    325:        for (; want < NOFILE; want++) {
                    326:                if (u.u_ofile[want] == NULL) {
                    327:                        u.u_pofile[want] = 0;
                    328:                        if (want > u.u_lastfile)
                    329:                                u.u_lastfile = want;
                    330:                        *result = want;
                    331:                        return (0);
                    332:                }
                    333:        }
                    334:        return (EMFILE);
                    335: }
                    336: 
                    337: /*
                    338:  * Check to see if any user file descriptors are available.
                    339:  */
                    340: ufavail()
                    341: {
                    342:        register int i, avail = 0;
                    343: 
                    344:        for (i = 0; i < NOFILE; i++)
                    345:                if (u.u_ofile[i] == NULL)
                    346:                        avail++;
                    347:        return (avail);
                    348: }
                    349: 
                    350: struct file *lastf;
                    351: /*
                    352:  * Allocate a user file descriptor
                    353:  * and a file structure.
                    354:  * Initialize the descriptor
                    355:  * to point at the file structure.
                    356:  */
                    357: falloc(resultfp, resultfd)
                    358:        struct file **resultfp;
                    359:        int *resultfd;
                    360: {
                    361:        register struct file *fp;
                    362:        int error, i;
                    363: 
                    364:        if (error = ufalloc(0, &i))
                    365:                return (error);
                    366:        if (lastf == 0)
                    367:                lastf = file;
                    368:        for (fp = lastf; fp < fileNFILE; fp++)
                    369:                if (fp->f_count == 0)
                    370:                        goto slot;
                    371:        for (fp = file; fp < lastf; fp++)
                    372:                if (fp->f_count == 0)
                    373:                        goto slot;
                    374:        tablefull("file");
                    375:        return (ENFILE);
                    376: slot:
                    377:        u.u_ofile[i] = fp;
                    378:        fp->f_count = 1;
                    379:        fp->f_data = 0;
                    380:        fp->f_offset = 0;
                    381:        fp->f_cred = u.u_cred;
                    382:        crhold(fp->f_cred);
                    383:        lastf = fp + 1;
                    384:        if (resultfp)
                    385:                *resultfp = fp;
                    386:        if (resultfd)
                    387:                *resultfd = i;
                    388:        return (0);
                    389: }
                    390: 
                    391: /*
                    392:  * Internal form of close.
                    393:  * Decrement reference count on file structure.
                    394:  */
                    395: closef(fp)
                    396:        register struct file *fp;
                    397: {
                    398:        int error;
                    399: 
                    400:        if (fp == NULL)
                    401:                return (0);
                    402:        if (fp->f_count > 1) {
                    403:                fp->f_count--;
                    404:                return (0);
                    405:        }
                    406:        if (fp->f_count < 1)
                    407:                panic("closef: count < 1");
                    408:        error = (*fp->f_ops->fo_close)(fp);
                    409:        crfree(fp->f_cred);
                    410:        fp->f_count = 0;
                    411:        return (error);
                    412: }
                    413: 
                    414: /*
                    415:  * Apply an advisory lock on a file descriptor.
                    416:  */
                    417: /* ARGSUSED */
                    418: flock(p, uap, retval)
                    419:        struct proc *p;
                    420:        register struct args {
                    421:                int     fdes;
                    422:                int     how;
                    423:        } *uap;
                    424:        int *retval;
                    425: {
                    426:        register struct file *fp;
                    427: 
                    428:        if ((unsigned)uap->fdes >= NOFILE ||
                    429:            (fp = u.u_ofile[uap->fdes]) == NULL)
                    430:                return (EBADF);
                    431:        if (fp->f_type != DTYPE_VNODE)
                    432:                return (EOPNOTSUPP);
                    433:        if (uap->how & LOCK_UN) {
                    434:                vn_unlock(fp, FSHLOCK|FEXLOCK);
                    435:                return (0);
                    436:        }
                    437:        if ((uap->how & (LOCK_SH | LOCK_EX)) == 0)
                    438:                return (0);                             /* error? */
                    439:        if (uap->how & LOCK_EX)
                    440:                uap->how &= ~LOCK_SH;
                    441:        /* avoid work... */
                    442:        if ((fp->f_flag & FEXLOCK) && (uap->how & LOCK_EX) ||
                    443:            (fp->f_flag & FSHLOCK) && (uap->how & LOCK_SH))
                    444:                return (0);
                    445:        return (vn_lock(fp, uap->how));
                    446: }
                    447: 
                    448: /*
                    449:  * File Descriptor pseudo-device driver (/dev/fd/).
                    450:  *
                    451:  * Opening minor device N dup()s the file (if any) connected to file
                    452:  * descriptor N belonging to the calling process.  Note that this driver
                    453:  * consists of only the ``open()'' routine, because all subsequent
                    454:  * references to this file will be direct to the other driver.
                    455:  */
                    456: /* ARGSUSED */
                    457: fdopen(dev, mode, type)
                    458:        dev_t dev;
                    459:        int mode, type;
                    460: {
                    461:        struct proc *p = u.u_procp;             /* XXX */
                    462: 
                    463:        /*
                    464:         * XXX Kludge: set p->p_dupfd to contain the value of the
                    465:         * the file descriptor being sought for duplication. The error 
                    466:         * return ensures that the vnode for this device will be released
                    467:         * by vn_open. Open will detect this special error and take the
                    468:         * actions in dupfdopen below. Other callers of vn_open or VOP_OPEN
                    469:         * will simply report the error.
                    470:         */
                    471:        p->p_dupfd = minor(dev);
                    472:        return (ENODEV);
                    473: }
                    474: 
                    475: /*
                    476:  * Duplicate the specified descriptor to a free descriptor.
                    477:  */
                    478: dupfdopen(indx, dfd, mode)
                    479:        register int indx, dfd;
                    480:        int mode;
                    481: {
                    482:        register struct file *wfp;
                    483:        struct file *fp;
                    484:        
                    485:        /*
                    486:         * If the to-be-dup'd fd number is greater than the allowed number
                    487:         * of file descriptors, or the fd to be dup'd has already been
                    488:         * closed, reject.  Note, check for new == old is necessary as
                    489:         * falloc could allocate an already closed to-be-dup'd descriptor
                    490:         * as the new descriptor.
                    491:         */
                    492:        fp = u.u_ofile[indx];
                    493:        if ((u_int)dfd >= NOFILE || (wfp = u.u_ofile[dfd]) == NULL ||
                    494:            fp == wfp)
                    495:                return (EBADF);
                    496: 
                    497:        /*
                    498:         * Check that the mode the file is being opened for is a subset 
                    499:         * of the mode of the existing descriptor.
                    500:         */
                    501:        if (((mode & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag)
                    502:                return (EACCES);
                    503:        u.u_ofile[indx] = wfp;
                    504:        u.u_pofile[indx] = u.u_pofile[dfd];
                    505:        wfp->f_count++;
                    506:        if (indx > u.u_lastfile)
                    507:                u.u_lastfile = indx;
                    508:        return (0);
                    509: }

unix.superglobalmegacorp.com

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