Annotation of XNU/bsd/miscfs/fdesc/fdesc_vnops.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
                     23: /*
                     24:  * Copyright (c) 1992, 1993
                     25:  *     The Regents of the University of California.  All rights reserved.
                     26:  *
                     27:  * This code is derived from software donated to Berkeley by
                     28:  * Jan-Simon Pendry.
                     29:  *
                     30:  * Redistribution and use in source and binary forms, with or without
                     31:  * modification, are permitted provided that the following conditions
                     32:  * are met:
                     33:  * 1. Redistributions of source code must retain the above copyright
                     34:  *    notice, this list of conditions and the following disclaimer.
                     35:  * 2. Redistributions in binary form must reproduce the above copyright
                     36:  *    notice, this list of conditions and the following disclaimer in the
                     37:  *    documentation and/or other materials provided with the distribution.
                     38:  * 3. All advertising materials mentioning features or use of this software
                     39:  *    must display the following acknowledgement:
                     40:  *     This product includes software developed by the University of
                     41:  *     California, Berkeley and its contributors.
                     42:  * 4. Neither the name of the University nor the names of its contributors
                     43:  *    may be used to endorse or promote products derived from this software
                     44:  *    without specific prior written permission.
                     45:  *
                     46:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     47:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     48:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     49:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     50:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     51:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     52:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     53:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     54:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     55:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     56:  * SUCH DAMAGE.
                     57:  *
                     58:  *     @(#)fdesc_vnops.c       8.17 (Berkeley) 5/22/95
                     59:  *
                     60:  */
                     61: 
                     62: /*
                     63:  * /dev/fd Filesystem
                     64:  */
                     65: 
                     66: #include <sys/param.h>
                     67: #include <sys/systm.h>
                     68: #include <sys/types.h>
                     69: #include <sys/time.h>
                     70: #include <sys/proc.h>
                     71: #include <sys/kernel.h>        /* boottime */
                     72: #include <sys/resourcevar.h>
                     73: #include <sys/filedesc.h>
                     74: #include <sys/vnode.h>
                     75: #include <sys/malloc.h>
                     76: #include <sys/file.h>
                     77: #include <sys/stat.h>
                     78: #include <sys/mount.h>
                     79: #include <sys/namei.h>
                     80: #include <sys/buf.h>
                     81: #include <sys/dirent.h>
                     82: #include <vfs/vfs_support.h>
                     83: #include <miscfs/fdesc/fdesc.h>
                     84: 
                     85: #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
                     86: 
                     87: #define FDL_WANT       0x01
                     88: #define FDL_LOCKED     0x02
                     89: static int fdcache_lock;
                     90: 
                     91: dev_t devctty;
                     92: 
                     93: #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
                     94: FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
                     95: #endif
                     96: 
                     97: #define        NFDCACHE 4
                     98: 
                     99: #define FD_NHASH(ix) \
                    100:        (&fdhashtbl[(ix) & fdhash])
                    101: LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
                    102: u_long fdhash;
                    103: 
                    104: /*
                    105:  * Initialise cache headers
                    106:  */
                    107: fdesc_init(vfsp)
                    108:        struct vfsconf *vfsp;
                    109: {
                    110: 
                    111:        devctty = makedev(nchrdev, 0);
                    112:        fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash);
                    113: }
                    114: 
                    115: int
                    116: fdesc_allocvp(ftype, ix, mp, vpp)
                    117:        fdntype ftype;
                    118:        int ix;
                    119:        struct mount *mp;
                    120:        struct vnode **vpp;
                    121: {
                    122:        struct proc *p = current_proc();        /* XXX */
                    123:        struct fdhashhead *fc;
                    124:        struct fdescnode *fd;
                    125:        int error = 0;
                    126: 
                    127:        fc = FD_NHASH(ix);
                    128: loop:
                    129:        for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) {
                    130:                if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
                    131:                        if (vget(fd->fd_vnode, 0, p))
                    132:                                goto loop;
                    133:                        *vpp = fd->fd_vnode;
                    134:                        return (error);
                    135:                }
                    136:        }
                    137: 
                    138:        /*
                    139:         * otherwise lock the array while we call getnewvnode
                    140:         * since that can block.
                    141:         */ 
                    142:        if (fdcache_lock & FDL_LOCKED) {
                    143:                fdcache_lock |= FDL_WANT;
                    144:                sleep((caddr_t) &fdcache_lock, PINOD);
                    145:                goto loop;
                    146:        }
                    147:        fdcache_lock |= FDL_LOCKED;
                    148: 
                    149:        MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK);
                    150:        error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp);
                    151:        if (error) {
                    152:                FREE(fd, M_TEMP);
                    153:                goto out;
                    154:        }
                    155:        (*vpp)->v_data = fd;
                    156:        fd->fd_vnode = *vpp;
                    157:        fd->fd_type = ftype;
                    158:        fd->fd_fd = -1;
                    159:        fd->fd_link = 0;
                    160:        fd->fd_ix = ix;
                    161:        LIST_INSERT_HEAD(fc, fd, fd_hash);
                    162: 
                    163: out:
                    164:        fdcache_lock &= ~FDL_LOCKED;
                    165: 
                    166:        if (fdcache_lock & FDL_WANT) {
                    167:                fdcache_lock &= ~FDL_WANT;
                    168:                wakeup((caddr_t) &fdcache_lock);
                    169:        }
                    170: 
                    171:        return (error);
                    172: }
                    173: 
                    174: /*
                    175:  * vp is the current namei directory
                    176:  * ndp is the name to locate in that directory...
                    177:  */
                    178: int
                    179: fdesc_lookup(ap)
                    180:        struct vop_lookup_args /* {
                    181:                struct vnode * a_dvp;
                    182:                struct vnode ** a_vpp;
                    183:                struct componentname * a_cnp;
                    184:        } */ *ap;
                    185: {
                    186:        struct vnode **vpp = ap->a_vpp;
                    187:        struct vnode *dvp = ap->a_dvp;
                    188:        struct componentname *cnp = ap->a_cnp;
                    189:        char *pname = cnp->cn_nameptr;
                    190:        struct proc *p = cnp->cn_proc;
                    191:        int nfiles = p->p_fd->fd_nfiles;
                    192:        unsigned fd;
                    193:        int error;
                    194:        struct vnode *fvp;
                    195:        char *ln;
                    196: 
                    197:        VOP_UNLOCK(dvp, 0, p);
                    198:        if (cnp->cn_namelen == 1 && *pname == '.') {
                    199:                *vpp = dvp;
                    200:                VREF(dvp);      
                    201:                vn_lock(dvp, LK_SHARED | LK_RETRY, p);
                    202:                return (0);
                    203:        }
                    204: 
                    205:        switch (VTOFDESC(dvp)->fd_type) {
                    206:        default:
                    207:        case Flink:
                    208:        case Fdesc:
                    209:        case Fctty:
                    210:                error = ENOTDIR;
                    211:                goto bad;
                    212: 
                    213:        case Froot:
                    214:                if (cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
                    215:                        error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp);
                    216:                        if (error)
                    217:                                goto bad;
                    218:                        *vpp = fvp;
                    219:                        fvp->v_type = VDIR;
                    220:                        vn_lock(fvp, LK_SHARED | LK_RETRY, p);
                    221:                        return (0);
                    222:                }
                    223: 
                    224:                if (cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
                    225:                        struct vnode *ttyvp = cttyvp(p);
                    226:                        if (ttyvp == NULL) {
                    227:                                error = ENXIO;
                    228:                                goto bad;
                    229:                        }
                    230:                        error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp);
                    231:                        if (error)
                    232:                                goto bad;
                    233:                        *vpp = fvp;
                    234:                        fvp->v_type = VCHR;
                    235:                        vn_lock(fvp, LK_SHARED | LK_RETRY, p);
                    236:                        return (0);
                    237:                }
                    238: 
                    239:                ln = 0;
                    240:                switch (cnp->cn_namelen) {
                    241:                case 5:
                    242:                        if (bcmp(pname, "stdin", 5) == 0) {
                    243:                                ln = "fd/0";
                    244:                                fd = FD_STDIN;
                    245:                        }
                    246:                        break;
                    247:                case 6:
                    248:                        if (bcmp(pname, "stdout", 6) == 0) {
                    249:                                ln = "fd/1";
                    250:                                fd = FD_STDOUT;
                    251:                        } else
                    252:                        if (bcmp(pname, "stderr", 6) == 0) {
                    253:                                ln = "fd/2";
                    254:                                fd = FD_STDERR;
                    255:                        }
                    256:                        break;
                    257:                }
                    258: 
                    259:                if (ln) {
                    260:                        error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp);
                    261:                        if (error)
                    262:                                goto bad;
                    263:                        VTOFDESC(fvp)->fd_link = ln;
                    264:                        *vpp = fvp;
                    265:                        fvp->v_type = VLNK;
                    266:                        vn_lock(fvp, LK_SHARED | LK_RETRY, p);
                    267:                        return (0);
                    268:                } else {
                    269:                        error = ENOENT;
                    270:                        goto bad;
                    271:                }
                    272: 
                    273:                /* FALL THROUGH */
                    274: 
                    275:        case Fdevfd:
                    276:                if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) {
                    277:                        if (error = fdesc_root(dvp->v_mount, vpp))
                    278:                                goto bad;
                    279:                        return (0);
                    280:                }
                    281: 
                    282:                fd = 0;
                    283:                while (*pname >= '0' && *pname <= '9') {
                    284:                        fd = 10 * fd + *pname++ - '0';
                    285:                        if (fd >= nfiles)
                    286:                                break;
                    287:                }
                    288: 
                    289:                if (*pname != '\0') {
                    290:                        error = ENOENT;
                    291:                        goto bad;
                    292:                }
                    293: 
                    294:                if (fd >= nfiles ||
                    295:                                *fdfile(p, fd) == NULL ||
                    296:                                (*fdflags(p, fd) & UF_RESERVED)) {
                    297:                        error = EBADF;
                    298:                        goto bad;
                    299:                }
                    300: 
                    301:                error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp);
                    302:                if (error)
                    303:                        goto bad;
                    304:                VTOFDESC(fvp)->fd_fd = fd;
                    305:                vn_lock(fvp, LK_SHARED | LK_RETRY, p);
                    306:                *vpp = fvp;
                    307:                return (0);
                    308:        }
                    309: 
                    310: bad:;
                    311:        vn_lock(dvp, LK_SHARED | LK_RETRY, p);
                    312:        *vpp = NULL;
                    313:        return (error);
                    314: }
                    315: 
                    316: int
                    317: fdesc_open(ap)
                    318:        struct vop_open_args /* {
                    319:                struct vnode *a_vp;
                    320:                int  a_mode;
                    321:                struct ucred *a_cred;
                    322:                struct proc *a_p;
                    323:        } */ *ap;
                    324: {
                    325:        struct vnode *vp = ap->a_vp;
                    326:        int error = 0;
                    327: 
                    328:        switch (VTOFDESC(vp)->fd_type) {
                    329:        case Fdesc:
                    330:                /*
                    331:                 * XXX Kludge: set p->p_dupfd to contain the value of the
                    332:                 * the file descriptor being sought for duplication. The error 
                    333:                 * return ensures that the vnode for this device will be
                    334:                 * released by vn_open. Open will detect this special error and
                    335:                 * take the actions in dupfdopen.  Other callers of vn_open or
                    336:                 * VOP_OPEN will simply report the error.
                    337:                 */
                    338:                ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */
                    339:                error = ENODEV;
                    340:                break;
                    341: 
                    342:        case Fctty:
                    343:                error = cttyopen(devctty, ap->a_mode, 0, ap->a_p);
                    344:                break;
                    345:        }
                    346: 
                    347:        return (error);
                    348: }
                    349: 
                    350: static int
                    351: fdesc_attr(fd, vap, cred, p)
                    352:        int fd;
                    353:        struct vattr *vap;
                    354:        struct ucred *cred;
                    355:        struct proc *p;
                    356: {
                    357:        struct file *fp;
                    358:        struct stat stb;
                    359:        int error;
                    360: 
                    361:        if (error = fdgetf(p, fd, &fp))
                    362:                return (error);
                    363:        switch (fp->f_type) {
                    364:        case DTYPE_VNODE:
                    365:                error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
                    366:                if (error == 0 && vap->va_type == VDIR) {
                    367:                        /*
                    368:                         * directories can cause loops in the namespace,
                    369:                         * so turn off the 'x' bits to avoid trouble.
                    370:                         */
                    371:                        vap->va_mode &= ~((VEXEC)|(VEXEC>>3)|(VEXEC>>6));
                    372:                }
                    373:                break;
                    374: 
                    375:        case DTYPE_SOCKET:
                    376:                error = soo_stat((struct socket *)fp->f_data, &stb);
                    377:                if (error == 0) {
                    378:                        vattr_null(vap);
                    379:                        vap->va_type = VSOCK;
                    380:                        vap->va_mode = stb.st_mode;
                    381:                        vap->va_nlink = stb.st_nlink;
                    382:                        vap->va_uid = stb.st_uid;
                    383:                        vap->va_gid = stb.st_gid;
                    384:                        vap->va_fsid = stb.st_dev;
                    385:                        vap->va_fileid = stb.st_ino;
                    386:                        vap->va_size = stb.st_size;
                    387:                        vap->va_blocksize = stb.st_blksize;
                    388:                        vap->va_atime = stb.st_atimespec;
                    389:                        vap->va_mtime = stb.st_mtimespec;
                    390:                        vap->va_ctime = stb.st_ctimespec;
                    391:                        vap->va_gen = stb.st_gen;
                    392:                        vap->va_flags = stb.st_flags;
                    393:                        vap->va_rdev = stb.st_rdev;
                    394:                        vap->va_bytes = stb.st_blocks * stb.st_blksize;
                    395:                }
                    396:                break;
                    397: 
                    398:        default:
                    399:                panic("fdesc attr");
                    400:                break;
                    401:        }
                    402: 
                    403:        return (error);
                    404: }
                    405: 
                    406: int
                    407: fdesc_getattr(ap)
                    408:        struct vop_getattr_args /* {
                    409:                struct vnode *a_vp;
                    410:                struct vattr *a_vap;
                    411:                struct ucred *a_cred;
                    412:                struct proc *a_p;
                    413:        } */ *ap;
                    414: {
                    415:        struct vnode *vp = ap->a_vp;
                    416:        struct vattr *vap = ap->a_vap;
                    417:        unsigned fd;
                    418:        int error = 0;
                    419: 
                    420:        switch (VTOFDESC(vp)->fd_type) {
                    421:        case Froot:
                    422:        case Fdevfd:
                    423:        case Flink:
                    424:        case Fctty:
                    425:                bzero((caddr_t) vap, sizeof(*vap));
                    426:                vattr_null(vap);
                    427:                vap->va_fileid = VTOFDESC(vp)->fd_ix;
                    428: 
                    429:                vap->va_uid = 0;
                    430:                vap->va_gid = 0;
                    431:                vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
                    432:                vap->va_blocksize = DEV_BSIZE;
                    433:                vap->va_atime.tv_sec = boottime.tv_sec;
                    434:                vap->va_atime.tv_nsec = 0;
                    435:                vap->va_mtime = vap->va_atime;
                    436:                vap->va_ctime = vap->va_mtime;
                    437:                vap->va_gen = 0;
                    438:                vap->va_flags = 0;
                    439:                vap->va_rdev = 0;
                    440:                vap->va_bytes = 0;
                    441: 
                    442:                switch (VTOFDESC(vp)->fd_type) {
                    443:                case Flink:
                    444:                        vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
                    445:                        vap->va_type = VLNK;
                    446:                        vap->va_nlink = 1;
                    447:                        vap->va_size = strlen(VTOFDESC(vp)->fd_link);
                    448:                        break;
                    449: 
                    450:                case Fctty:
                    451:                        vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
                    452:                        vap->va_type = VCHR;
                    453:                        vap->va_nlink = 1;
                    454:                        vap->va_size = 0;
                    455:                        vap->va_rdev = devctty;
                    456:                        break;
                    457: 
                    458:                default:
                    459:                        vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
                    460:                        vap->va_type = VDIR;
                    461:                        vap->va_nlink = 2;
                    462:                        vap->va_size = DEV_BSIZE;
                    463:                        break;
                    464:                }
                    465:                break;
                    466: 
                    467:        case Fdesc:
                    468:                fd = VTOFDESC(vp)->fd_fd;
                    469:                error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p);
                    470:                break;
                    471: 
                    472:        default:
                    473:                panic("fdesc_getattr");
                    474:                break;  
                    475:        }
                    476: 
                    477:        if (error == 0)
                    478:                vp->v_type = vap->va_type;
                    479: 
                    480:        return (error);
                    481: }
                    482: 
                    483: int
                    484: fdesc_setattr(ap)
                    485:        struct vop_setattr_args /* {
                    486:                struct vnode *a_vp;
                    487:                struct vattr *a_vap;
                    488:                struct ucred *a_cred;
                    489:                struct proc *a_p;
                    490:        } */ *ap;
                    491: {
                    492:        struct file *fp;
                    493:        unsigned fd;
                    494:        int error;
                    495: 
                    496:        /*
                    497:         * Can't mess with the root vnode
                    498:         */
                    499:        switch (VTOFDESC(ap->a_vp)->fd_type) {
                    500:        case Fdesc:
                    501:                break;
                    502: 
                    503:        case Fctty:
                    504:                return (0);
                    505: 
                    506:        default:
                    507:                return (EACCES);
                    508:        }
                    509: 
                    510:        fd = VTOFDESC(ap->a_vp)->fd_fd;
                    511:        if (error = fdgetf(ap->a_p, fd, &fp))
                    512:                return (error);
                    513: 
                    514:        /*
                    515:         * Can setattr the underlying vnode, but not sockets!
                    516:         */
                    517:        switch (fp->f_type) {
                    518:        case DTYPE_VNODE:
                    519:                error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p);
                    520:                break;
                    521: 
                    522:        case DTYPE_SOCKET:
                    523:                error = 0;
                    524:                break;
                    525: 
                    526:        default:
                    527:                kprintf("fp->f_type = %d\n", fp->f_type);
                    528:         error = EBADF;
                    529:                break;
                    530:        }
                    531: 
                    532:        return (error);
                    533: }
                    534: 
                    535: #define UIO_MX 16
                    536: 
                    537: static struct dirtmp {
                    538:        u_long d_fileno;
                    539:        u_short d_reclen;
                    540:        u_short d_namlen;
                    541:        char d_name[8];
                    542: } rootent[] = {
                    543:        { FD_DEVFD, UIO_MX, 2, "fd" },
                    544:        { FD_STDIN, UIO_MX, 5, "stdin" },
                    545:        { FD_STDOUT, UIO_MX, 6, "stdout" },
                    546:        { FD_STDERR, UIO_MX, 6, "stderr" },
                    547:        { FD_CTTY, UIO_MX, 3, "tty" },
                    548:        { 0 }
                    549: };
                    550: 
                    551: int
                    552: fdesc_readdir(ap)
                    553:        struct vop_readdir_args /* {
                    554:                struct vnode *a_vp;
                    555:                struct uio *a_uio;
                    556:                struct ucred *a_cred;
                    557:                int *a_eofflag;
                    558:                u_long *a_cookies;
                    559:                int a_ncookies;
                    560:        } */ *ap;
                    561: {
                    562:        struct uio *uio = ap->a_uio;
                    563:        struct proc *p = uio->uio_procp;
                    564:        int i, error;
                    565: 
                    566:        /*
                    567:         * We don't allow exporting fdesc mounts, and currently local
                    568:         * requests do not need cookies.
                    569:         */
                    570:        if (ap->a_ncookies)
                    571:                panic("fdesc_readdir: not hungry");
                    572: 
                    573:        switch (VTOFDESC(ap->a_vp)->fd_type) {
                    574:        case Fctty:
                    575:                return (0);
                    576: 
                    577:        case Fdesc:
                    578:                return (ENOTDIR);
                    579: 
                    580:        default:
                    581:                break;
                    582:        }
                    583: 
                    584:        if (VTOFDESC(ap->a_vp)->fd_type == Froot) {
                    585:                struct dirent d;
                    586:                struct dirent *dp = &d;
                    587:                struct dirtmp *dt;
                    588:                int fd;
                    589: 
                    590:                i = uio->uio_offset / UIO_MX;
                    591:                error = 0;
                    592: 
                    593:                while (uio->uio_resid > 0) {
                    594:                        dt = &rootent[i];
                    595:                        if (dt->d_fileno == 0) {
                    596:                                /**eofflagp = 1;*/
                    597:                                break;
                    598:                        }
                    599:                        i++;
                    600:                        
                    601:                        switch (dt->d_fileno) {
                    602:                        case FD_CTTY:
                    603:                                if (cttyvp(uio->uio_procp) == NULL)
                    604:                                        continue;
                    605:                                break;
                    606: 
                    607:                        case FD_STDIN:
                    608:                        case FD_STDOUT:
                    609:                        case FD_STDERR:
                    610:                                fd = dt->d_fileno - FD_STDIN;
                    611:                                if (fd >= p->p_fd->fd_nfiles)
                    612:                                        continue;
                    613:                                if (*fdfile(p, fd) == NULL &&
                    614:                                                !(*fdflags(p, fd) &
                    615:                                                        UF_RESERVED))
                    616:                                        continue;
                    617:                                break;
                    618:                        }
                    619:                        bzero((caddr_t) dp, UIO_MX);
                    620:                        dp->d_fileno = dt->d_fileno;
                    621:                        dp->d_namlen = dt->d_namlen;
                    622:                        dp->d_type = DT_UNKNOWN;
                    623:                        dp->d_reclen = dt->d_reclen;
                    624:                        bcopy(dt->d_name, dp->d_name, dp->d_namlen+1);
                    625:                        error = uiomove((caddr_t) dp, UIO_MX, uio);
                    626:                        if (error)
                    627:                                break;
                    628:                }
                    629:                uio->uio_offset = i * UIO_MX;
                    630:                return (error);
                    631:        }
                    632: 
                    633:        i = uio->uio_offset / UIO_MX;
                    634:        error = 0;
                    635:        while (uio->uio_resid > 0) {
                    636:                if (i >= p->p_fd->fd_nfiles)
                    637:                        break;
                    638: 
                    639:                if (*fdfile(p, i) != NULL && !(*fdflags(p, i) & UF_RESERVED)) {
                    640:                        struct dirent d;
                    641:                        struct dirent *dp = &d;
                    642: 
                    643:                        bzero((caddr_t) dp, UIO_MX);
                    644: 
                    645:                        dp->d_namlen = sprintf(dp->d_name, "%d", i);
                    646:                        dp->d_reclen = UIO_MX;
                    647:                        dp->d_type = DT_UNKNOWN;
                    648:                        dp->d_fileno = i + FD_STDIN;
                    649:                        /*
                    650:                         * And ship to userland
                    651:                         */
                    652:                        error = uiomove((caddr_t) dp, UIO_MX, uio);
                    653:                        if (error)
                    654:                                break;
                    655:                }
                    656:                i++;
                    657:        }
                    658: 
                    659:        uio->uio_offset = i * UIO_MX;
                    660:        return (error);
                    661: }
                    662: 
                    663: int
                    664: fdesc_readlink(ap)
                    665:        struct vop_readlink_args /* {
                    666:                struct vnode *a_vp;
                    667:                struct uio *a_uio;
                    668:                struct ucred *a_cred;
                    669:        } */ *ap;
                    670: {
                    671:        struct vnode *vp = ap->a_vp;
                    672:        int error;
                    673: 
                    674:        if (vp->v_type != VLNK)
                    675:                return (EPERM);
                    676: 
                    677:        if (VTOFDESC(vp)->fd_type == Flink) {
                    678:                char *ln = VTOFDESC(vp)->fd_link;
                    679:                error = uiomove(ln, strlen(ln), ap->a_uio);
                    680:        } else {
                    681:                error = EOPNOTSUPP;
                    682:        }
                    683: 
                    684:        return (error);
                    685: }
                    686: 
                    687: int
                    688: fdesc_read(ap)
                    689:        struct vop_read_args /* {
                    690:                struct vnode *a_vp;
                    691:                struct uio *a_uio;
                    692:                int  a_ioflag;
                    693:                struct ucred *a_cred;
                    694:        } */ *ap;
                    695: {
                    696:        int error = EOPNOTSUPP;
                    697: 
                    698:        switch (VTOFDESC(ap->a_vp)->fd_type) {
                    699:        case Fctty:
                    700:                error = cttyread(devctty, ap->a_uio, ap->a_ioflag);
                    701:                break;
                    702: 
                    703:        default:
                    704:                error = EOPNOTSUPP;
                    705:                break;
                    706:        }
                    707:        
                    708:        return (error);
                    709: }
                    710: 
                    711: int
                    712: fdesc_write(ap)
                    713:        struct vop_write_args /* {
                    714:                struct vnode *a_vp;
                    715:                struct uio *a_uio;
                    716:                int  a_ioflag;
                    717:                struct ucred *a_cred;
                    718:        } */ *ap;
                    719: {
                    720:        int error = EOPNOTSUPP;
                    721: 
                    722:        switch (VTOFDESC(ap->a_vp)->fd_type) {
                    723:        case Fctty:
                    724:                error = cttywrite(devctty, ap->a_uio, ap->a_ioflag);
                    725:                break;
                    726: 
                    727:        default:
                    728:                error = EOPNOTSUPP;
                    729:                break;
                    730:        }
                    731:        
                    732:        return (error);
                    733: }
                    734: 
                    735: int
                    736: fdesc_ioctl(ap)
                    737:        struct vop_ioctl_args /* {
                    738:                struct vnode *a_vp;
                    739:                int  a_command;
                    740:                caddr_t  a_data;
                    741:                int  a_fflag;
                    742:                struct ucred *a_cred;
                    743:                struct proc *a_p;
                    744:        } */ *ap;
                    745: {
                    746:        int error = EOPNOTSUPP;
                    747: 
                    748:        switch (VTOFDESC(ap->a_vp)->fd_type) {
                    749:        case Fctty:
                    750:                error = cttyioctl(devctty, ap->a_command, ap->a_data,
                    751:                                        ap->a_fflag, ap->a_p);
                    752:                break;
                    753: 
                    754:        default:
                    755:                error = EOPNOTSUPP;
                    756:                break;
                    757:        }
                    758:        
                    759:        return (error);
                    760: }
                    761: 
                    762: int
                    763: fdesc_select(ap)
                    764:        struct vop_select_args /* {
                    765:                struct vnode *a_vp;
                    766:                int  a_which;
                    767:                int  a_fflags;
                    768:                struct ucred *a_cred;
                    769:                struct proc *a_p;
                    770:        } */ *ap;
                    771: {
                    772:        int error = EOPNOTSUPP;
                    773: 
                    774:        switch (VTOFDESC(ap->a_vp)->fd_type) {
                    775:        case Fctty:
                    776:                error = cttyselect(devctty, ap->a_fflags, ap->a_p);
                    777:                break;
                    778: 
                    779:        default:
                    780:                error = EOPNOTSUPP;
                    781:                break;
                    782:        }
                    783:        
                    784:        return (error);
                    785: }
                    786: 
                    787: int
                    788: fdesc_inactive(ap)
                    789:        struct vop_inactive_args /* {
                    790:                struct vnode *a_vp;
                    791:                struct proc *a_p;
                    792:        } */ *ap;
                    793: {
                    794:        struct vnode *vp = ap->a_vp;
                    795: 
                    796:        /*
                    797:         * Clear out the v_type field to avoid
                    798:         * nasty things happening in vgone().
                    799:         */
                    800:        VOP_UNLOCK(vp, 0, ap->a_p);
                    801:        vp->v_type = VNON;
                    802:        return (0);
                    803: }
                    804: 
                    805: int
                    806: fdesc_reclaim(ap)
                    807:        struct vop_reclaim_args /* {
                    808:                struct vnode *a_vp;
                    809:        } */ *ap;
                    810: {
                    811:        struct vnode *vp = ap->a_vp;
                    812:        struct fdescnode *fd = VTOFDESC(vp);
                    813: 
                    814:        LIST_REMOVE(fd, fd_hash);
                    815:        FREE(vp->v_data, M_TEMP);
                    816:        vp->v_data = 0;
                    817: 
                    818:        return (0);
                    819: }
                    820: 
                    821: /*
                    822:  * Return POSIX pathconf information applicable to special devices.
                    823:  */
                    824: fdesc_pathconf(ap)
                    825:        struct vop_pathconf_args /* {
                    826:                struct vnode *a_vp;
                    827:                int a_name;
                    828:                int *a_retval;
                    829:        } */ *ap;
                    830: {
                    831: 
                    832:        switch (ap->a_name) {
                    833:        case _PC_LINK_MAX:
                    834:                *ap->a_retval = LINK_MAX;
                    835:                return (0);
                    836:        case _PC_MAX_CANON:
                    837:                *ap->a_retval = MAX_CANON;
                    838:                return (0);
                    839:        case _PC_MAX_INPUT:
                    840:                *ap->a_retval = MAX_INPUT;
                    841:                return (0);
                    842:        case _PC_PIPE_BUF:
                    843:                *ap->a_retval = PIPE_BUF;
                    844:                return (0);
                    845:        case _PC_CHOWN_RESTRICTED:
                    846:                *ap->a_retval = 1;
                    847:                return (0);
                    848:        case _PC_VDISABLE:
                    849:                *ap->a_retval = _POSIX_VDISABLE;
                    850:                return (0);
                    851:        default:
                    852:                return (EINVAL);
                    853:        }
                    854:        /* NOTREACHED */
                    855: }
                    856: 
                    857: /*
                    858:  * Print out the contents of a /dev/fd vnode.
                    859:  */
                    860: /* ARGSUSED */
                    861: int
                    862: fdesc_print(ap)
                    863:        struct vop_print_args /* {
                    864:                struct vnode *a_vp;
                    865:        } */ *ap;
                    866: {
                    867: 
                    868:        printf("tag VT_NON, fdesc vnode\n");
                    869:        return (0);
                    870: }
                    871: 
                    872: /*void*/
                    873: int
                    874: fdesc_vfree(ap)
                    875:        struct vop_vfree_args /* {
                    876:                struct vnode *a_pvp;
                    877:                ino_t a_ino;
                    878:                int a_mode;
                    879:        } */ *ap;
                    880: {
                    881: 
                    882:        return (0);
                    883: }
                    884: 
                    885: /*
                    886:  * /dev/fd "should never get here" operation
                    887:  */
                    888: int
                    889: fdesc_badop()
                    890: {
                    891: 
                    892:        panic("fdesc: bad op");
                    893:        /* NOTREACHED */
                    894: }
                    895: 
                    896: /* Pagein  */
                    897: fdesc_pagein(ap)
                    898:        struct vop_pagein_args /* {
                    899:                struct vnode *a_vp;
                    900:                struct uio *a_uio;
                    901:                int a_ioflag;
                    902:                struct ucred *a_cred;
                    903:        } */ *ap;
                    904: {
                    905:        /* pass thru to read */ 
                    906:        return (VOP_READ(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
                    907: }
                    908: 
                    909: /* Pageout  */
                    910: fdesc_pageout(ap)
                    911:        struct vop_pageout_args /* {
                    912:                struct vnode *a_vp;
                    913:                struct uio *a_uio;
                    914:                int a_ioflag;
                    915:                struct ucred *a_cred;
                    916:        } */ *ap;
                    917: {
                    918:        /* pass thru to write */ 
                    919:        return (VOP_WRITE(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
                    920: }
                    921: 
                    922: #define fdesc_create ((int (*) __P((struct  vop_create_args *)))eopnotsupp)
                    923: #define fdesc_mknod ((int (*) __P((struct  vop_mknod_args *)))eopnotsupp)
                    924: #define fdesc_close ((int (*) __P((struct  vop_close_args *)))nullop)
                    925: #define fdesc_access ((int (*) __P((struct  vop_access_args *)))nullop)
                    926: #define fdesc_mmap ((int (*) __P((struct  vop_mmap_args *)))eopnotsupp)
                    927: #define        fdesc_revoke vop_revoke
                    928: #define fdesc_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
                    929: #define fdesc_seek ((int (*) __P((struct  vop_seek_args *)))nullop)
                    930: #define fdesc_remove ((int (*) __P((struct  vop_remove_args *)))eopnotsupp)
                    931: #define fdesc_link ((int (*) __P((struct  vop_link_args *)))eopnotsupp)
                    932: #define fdesc_rename ((int (*) __P((struct  vop_rename_args *)))eopnotsupp)
                    933: #define fdesc_mkdir ((int (*) __P((struct  vop_mkdir_args *)))eopnotsupp)
                    934: #define fdesc_rmdir ((int (*) __P((struct  vop_rmdir_args *)))eopnotsupp)
                    935: #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
                    936: #define fdesc_abortop ((int (*) __P((struct  vop_abortop_args *)))nullop)
                    937: #define fdesc_lock ((int (*) __P((struct  vop_lock_args *)))vop_nolock)
                    938: #define fdesc_unlock ((int (*) __P((struct  vop_unlock_args *)))vop_nounlock)
                    939: #define fdesc_bmap ((int (*) __P((struct  vop_bmap_args *)))fdesc_badop)
                    940: #define fdesc_strategy ((int (*) __P((struct  vop_strategy_args *)))fdesc_badop)
                    941: #define fdesc_islocked \
                    942:        ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
                    943: #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
                    944: #define fdesc_blkatoff \
                    945:        ((int (*) __P((struct  vop_blkatoff_args *)))eopnotsupp)
                    946: #define fdesc_valloc ((int(*) __P(( \
                    947:                struct vnode *pvp, \
                    948:                int mode, \
                    949:                struct ucred *cred, \
                    950:                struct vnode **vpp))) eopnotsupp)
                    951: #define fdesc_truncate \
                    952:        ((int (*) __P((struct  vop_truncate_args *)))eopnotsupp)
                    953: #define fdesc_update ((int (*) __P((struct  vop_update_args *)))eopnotsupp)
                    954: #define fdesc_bwrite ((int (*) __P((struct  vop_bwrite_args *)))eopnotsupp)
                    955: 
                    956: int (**fdesc_vnodeop_p)();
                    957: struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
                    958:        { &vop_default_desc, vn_default_error },
                    959:        { &vop_lookup_desc, fdesc_lookup },     /* lookup */
                    960:        { &vop_create_desc, fdesc_create },     /* create */
                    961:        { &vop_mknod_desc, fdesc_mknod },       /* mknod */
                    962:        { &vop_open_desc, fdesc_open },         /* open */
                    963:        { &vop_close_desc, fdesc_close },       /* close */
                    964:        { &vop_access_desc, fdesc_access },     /* access */
                    965:        { &vop_getattr_desc, fdesc_getattr },   /* getattr */
                    966:        { &vop_setattr_desc, fdesc_setattr },   /* setattr */
                    967:        { &vop_read_desc, fdesc_read },         /* read */
                    968:        { &vop_write_desc, fdesc_write },       /* write */
                    969:        { &vop_ioctl_desc, fdesc_ioctl },       /* ioctl */
                    970:        { &vop_select_desc, fdesc_select },     /* select */
                    971:        { &vop_revoke_desc, fdesc_revoke },     /* revoke */
                    972:        { &vop_mmap_desc, fdesc_mmap },         /* mmap */
                    973:        { &vop_fsync_desc, fdesc_fsync },       /* fsync */
                    974:        { &vop_seek_desc, fdesc_seek },         /* seek */
                    975:        { &vop_remove_desc, fdesc_remove },     /* remove */
                    976:        { &vop_link_desc, fdesc_link },         /* link */
                    977:        { &vop_rename_desc, fdesc_rename },     /* rename */
                    978:        { &vop_mkdir_desc, fdesc_mkdir },       /* mkdir */
                    979:        { &vop_rmdir_desc, fdesc_rmdir },       /* rmdir */
                    980:        { &vop_symlink_desc, fdesc_symlink },   /* symlink */
                    981:        { &vop_readdir_desc, fdesc_readdir },   /* readdir */
                    982:        { &vop_readlink_desc, fdesc_readlink }, /* readlink */
                    983:        { &vop_abortop_desc, fdesc_abortop },   /* abortop */
                    984:        { &vop_inactive_desc, fdesc_inactive }, /* inactive */
                    985:        { &vop_reclaim_desc, fdesc_reclaim },   /* reclaim */
                    986:        { &vop_lock_desc, fdesc_lock },         /* lock */
                    987:        { &vop_unlock_desc, fdesc_unlock },     /* unlock */
                    988:        { &vop_bmap_desc, fdesc_bmap },         /* bmap */
                    989:        { &vop_strategy_desc, fdesc_strategy }, /* strategy */
                    990:        { &vop_print_desc, fdesc_print },       /* print */
                    991:        { &vop_islocked_desc, fdesc_islocked }, /* islocked */
                    992:        { &vop_pathconf_desc, fdesc_pathconf }, /* pathconf */
                    993:        { &vop_advlock_desc, fdesc_advlock },   /* advlock */
                    994:        { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */
                    995:        { &vop_valloc_desc, fdesc_valloc },     /* valloc */
                    996:        { &vop_vfree_desc, fdesc_vfree },       /* vfree */
                    997:        { &vop_truncate_desc, fdesc_truncate }, /* truncate */
                    998:        { &vop_update_desc, fdesc_update },     /* update */
                    999:        { &vop_bwrite_desc, fdesc_bwrite },     /* bwrite */
                   1000:        { &vop_bwrite_desc, fdesc_pagein },     /* pagein */
                   1001:        { &vop_bwrite_desc, fdesc_pageout },    /* pageout */
                   1002:         { &vop_copyfile_desc, err_copyfile },        /* Copyfile */
                   1003:        { (struct vnodeop_desc*)NULL, (int(*)())NULL }
                   1004: };
                   1005: struct vnodeopv_desc fdesc_vnodeop_opv_desc =
                   1006:        { &fdesc_vnodeop_p, fdesc_vnodeop_entries };

unix.superglobalmegacorp.com

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