Annotation of XNU/bsd/miscfs/fdesc/fdesc_vnops.c, revision 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.