Annotation of kernel/bsd/miscfs/fdesc/fdesc_vnops.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
        !            26: /*
        !            27:  * Copyright (c) 1992, 1993
        !            28:  *     The Regents of the University of California.  All rights reserved.
        !            29:  *
        !            30:  * This code is derived from software donated to Berkeley by
        !            31:  * Jan-Simon Pendry.
        !            32:  *
        !            33:  * Redistribution and use in source and binary forms, with or without
        !            34:  * modification, are permitted provided that the following conditions
        !            35:  * are met:
        !            36:  * 1. Redistributions of source code must retain the above copyright
        !            37:  *    notice, this list of conditions and the following disclaimer.
        !            38:  * 2. Redistributions in binary form must reproduce the above copyright
        !            39:  *    notice, this list of conditions and the following disclaimer in the
        !            40:  *    documentation and/or other materials provided with the distribution.
        !            41:  * 3. All advertising materials mentioning features or use of this software
        !            42:  *    must display the following acknowledgement:
        !            43:  *     This product includes software developed by the University of
        !            44:  *     California, Berkeley and its contributors.
        !            45:  * 4. Neither the name of the University nor the names of its contributors
        !            46:  *    may be used to endorse or promote products derived from this software
        !            47:  *    without specific prior written permission.
        !            48:  *
        !            49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            59:  * SUCH DAMAGE.
        !            60:  *
        !            61:  *     @(#)fdesc_vnops.c       8.17 (Berkeley) 5/22/95
        !            62:  *
        !            63:  */
        !            64: 
        !            65: /*
        !            66:  * /dev/fd Filesystem
        !            67:  */
        !            68: 
        !            69: #include <sys/param.h>
        !            70: #include <sys/systm.h>
        !            71: #include <sys/types.h>
        !            72: #include <sys/time.h>
        !            73: #include <sys/proc.h>
        !            74: #include <sys/kernel.h>        /* boottime */
        !            75: #include <sys/resourcevar.h>
        !            76: #include <sys/filedesc.h>
        !            77: #include <sys/vnode.h>
        !            78: #include <sys/malloc.h>
        !            79: #include <sys/file.h>
        !            80: #include <sys/stat.h>
        !            81: #include <sys/mount.h>
        !            82: #include <sys/namei.h>
        !            83: #include <sys/buf.h>
        !            84: #include <sys/dirent.h>
        !            85: #include <miscfs/fdesc/fdesc.h>
        !            86: 
        !            87: #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL)
        !            88: 
        !            89: #define FDL_WANT       0x01
        !            90: #define FDL_LOCKED     0x02
        !            91: static int fdcache_lock;
        !            92: 
        !            93: dev_t devctty;
        !            94: 
        !            95: #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
        !            96: FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
        !            97: #endif
        !            98: 
        !            99: #define        NFDCACHE 4
        !           100: 
        !           101: #define FD_NHASH(ix) \
        !           102:        (&fdhashtbl[(ix) & fdhash])
        !           103: LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl;
        !           104: u_long fdhash;
        !           105: 
        !           106: /*
        !           107:  * Initialise cache headers
        !           108:  */
        !           109: fdesc_init(vfsp)
        !           110:        struct vfsconf *vfsp;
        !           111: {
        !           112: 
        !           113:        devctty = makedev(nchrdev, 0);
        !           114:        fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash);
        !           115: }
        !           116: 
        !           117: int
        !           118: fdesc_allocvp(ftype, ix, mp, vpp)
        !           119:        fdntype ftype;
        !           120:        int ix;
        !           121:        struct mount *mp;
        !           122:        struct vnode **vpp;
        !           123: {
        !           124:        struct proc *p = current_proc();        /* XXX */
        !           125:        struct fdhashhead *fc;
        !           126:        struct fdescnode *fd;
        !           127:        int error = 0;
        !           128: 
        !           129:        fc = FD_NHASH(ix);
        !           130: loop:
        !           131:        for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) {
        !           132:                if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) {
        !           133:                        if (vget(fd->fd_vnode, 0, p))
        !           134:                                goto loop;
        !           135:                        *vpp = fd->fd_vnode;
        !           136:                        return (error);
        !           137:                }
        !           138:        }
        !           139: 
        !           140:        /*
        !           141:         * otherwise lock the array while we call getnewvnode
        !           142:         * since that can block.
        !           143:         */ 
        !           144:        if (fdcache_lock & FDL_LOCKED) {
        !           145:                fdcache_lock |= FDL_WANT;
        !           146:                sleep((caddr_t) &fdcache_lock, PINOD);
        !           147:                goto loop;
        !           148:        }
        !           149:        fdcache_lock |= FDL_LOCKED;
        !           150: 
        !           151:        error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp);
        !           152:        if (error)
        !           153:                goto out;
        !           154:        MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK);
        !           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 = VFIFO;
        !           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:                switch (VTOFDESC(vp)->fd_type) {
        !           430:                case Flink:
        !           431:                        vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
        !           432:                        vap->va_type = VLNK;
        !           433:                        vap->va_nlink = 1;
        !           434:                        vap->va_size = strlen(VTOFDESC(vp)->fd_link);
        !           435:                        break;
        !           436: 
        !           437:                case Fctty:
        !           438:                        vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
        !           439:                        vap->va_type = VFIFO;
        !           440:                        vap->va_nlink = 1;
        !           441:                        vap->va_size = 0;
        !           442:                        break;
        !           443: 
        !           444:                default:
        !           445:                        vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
        !           446:                        vap->va_type = VDIR;
        !           447:                        vap->va_nlink = 2;
        !           448:                        vap->va_size = DEV_BSIZE;
        !           449:                        break;
        !           450:                }
        !           451:                vap->va_uid = 0;
        !           452:                vap->va_gid = 0;
        !           453:                vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
        !           454:                vap->va_blocksize = DEV_BSIZE;
        !           455:                vap->va_atime.tv_sec = boottime.tv_sec;
        !           456:                vap->va_atime.tv_nsec = 0;
        !           457:                vap->va_mtime = vap->va_atime;
        !           458:                vap->va_ctime = vap->va_mtime;
        !           459:                vap->va_gen = 0;
        !           460:                vap->va_flags = 0;
        !           461:                vap->va_rdev = 0;
        !           462:                vap->va_bytes = 0;
        !           463:                break;
        !           464: 
        !           465:        case Fdesc:
        !           466:                fd = VTOFDESC(vp)->fd_fd;
        !           467:                error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p);
        !           468:                break;
        !           469: 
        !           470:        default:
        !           471:                panic("fdesc_getattr");
        !           472:                break;  
        !           473:        }
        !           474: 
        !           475:        if (error == 0)
        !           476:                vp->v_type = vap->va_type;
        !           477: 
        !           478:        return (error);
        !           479: }
        !           480: 
        !           481: int
        !           482: fdesc_setattr(ap)
        !           483:        struct vop_setattr_args /* {
        !           484:                struct vnode *a_vp;
        !           485:                struct vattr *a_vap;
        !           486:                struct ucred *a_cred;
        !           487:                struct proc *a_p;
        !           488:        } */ *ap;
        !           489: {
        !           490:        struct file *fp;
        !           491:        unsigned fd;
        !           492:        int error;
        !           493: 
        !           494:        /*
        !           495:         * Can't mess with the root vnode
        !           496:         */
        !           497:        switch (VTOFDESC(ap->a_vp)->fd_type) {
        !           498:        case Fdesc:
        !           499:                break;
        !           500: 
        !           501:        case Fctty:
        !           502:                return (0);
        !           503: 
        !           504:        default:
        !           505:                return (EACCES);
        !           506:        }
        !           507: 
        !           508:        fd = VTOFDESC(ap->a_vp)->fd_fd;
        !           509:        if (error = fdgetf(ap->a_p, fd, &fp))
        !           510:                return (error);
        !           511: 
        !           512:        /*
        !           513:         * Can setattr the underlying vnode, but not sockets!
        !           514:         */
        !           515:        switch (fp->f_type) {
        !           516:        case DTYPE_VNODE:
        !           517:                error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p);
        !           518:                break;
        !           519: 
        !           520:        case DTYPE_SOCKET:
        !           521:                error = 0;
        !           522:                break;
        !           523: 
        !           524:        default:
        !           525:                kprintf("fp->f_type = %d\n", fp->f_type);
        !           526:         error = EBADF;
        !           527:                break;
        !           528:        }
        !           529: 
        !           530:        return (error);
        !           531: }
        !           532: 
        !           533: #define UIO_MX 16
        !           534: 
        !           535: static struct dirtmp {
        !           536:        u_long d_fileno;
        !           537:        u_short d_reclen;
        !           538:        u_short d_namlen;
        !           539:        char d_name[8];
        !           540: } rootent[] = {
        !           541:        { FD_DEVFD, UIO_MX, 2, "fd" },
        !           542:        { FD_STDIN, UIO_MX, 5, "stdin" },
        !           543:        { FD_STDOUT, UIO_MX, 6, "stdout" },
        !           544:        { FD_STDERR, UIO_MX, 6, "stderr" },
        !           545:        { FD_CTTY, UIO_MX, 3, "tty" },
        !           546:        { 0 }
        !           547: };
        !           548: 
        !           549: int
        !           550: fdesc_readdir(ap)
        !           551:        struct vop_readdir_args /* {
        !           552:                struct vnode *a_vp;
        !           553:                struct uio *a_uio;
        !           554:                struct ucred *a_cred;
        !           555:                int *a_eofflag;
        !           556:                u_long *a_cookies;
        !           557:                int a_ncookies;
        !           558:        } */ *ap;
        !           559: {
        !           560:        struct uio *uio = ap->a_uio;
        !           561:        struct proc *p = uio->uio_procp;
        !           562:        int i, error;
        !           563: 
        !           564:        /*
        !           565:         * We don't allow exporting fdesc mounts, and currently local
        !           566:         * requests do not need cookies.
        !           567:         */
        !           568:        if (ap->a_ncookies)
        !           569:                panic("fdesc_readdir: not hungry");
        !           570: 
        !           571:        switch (VTOFDESC(ap->a_vp)->fd_type) {
        !           572:        case Fctty:
        !           573:                return (0);
        !           574: 
        !           575:        case Fdesc:
        !           576:                return (ENOTDIR);
        !           577: 
        !           578:        default:
        !           579:                break;
        !           580:        }
        !           581: 
        !           582:        if (VTOFDESC(ap->a_vp)->fd_type == Froot) {
        !           583:                struct dirent d;
        !           584:                struct dirent *dp = &d;
        !           585:                struct dirtmp *dt;
        !           586:                int fd;
        !           587: 
        !           588:                i = uio->uio_offset / UIO_MX;
        !           589:                error = 0;
        !           590: 
        !           591:                while (uio->uio_resid > 0) {
        !           592:                        dt = &rootent[i];
        !           593:                        if (dt->d_fileno == 0) {
        !           594:                                /**eofflagp = 1;*/
        !           595:                                break;
        !           596:                        }
        !           597:                        i++;
        !           598:                        
        !           599:                        switch (dt->d_fileno) {
        !           600:                        case FD_CTTY:
        !           601:                                if (cttyvp(uio->uio_procp) == NULL)
        !           602:                                        continue;
        !           603:                                break;
        !           604: 
        !           605:                        case FD_STDIN:
        !           606:                        case FD_STDOUT:
        !           607:                        case FD_STDERR:
        !           608:                                fd = dt->d_fileno - FD_STDIN;
        !           609:                                if (fd >= p->p_fd->fd_nfiles)
        !           610:                                        continue;
        !           611:                                if (*fdfile(p, fd) == NULL &&
        !           612:                                                !(*fdflags(p, fd) &
        !           613:                                                        UF_RESERVED))
        !           614:                                        continue;
        !           615:                                break;
        !           616:                        }
        !           617:                        bzero((caddr_t) dp, UIO_MX);
        !           618:                        dp->d_fileno = dt->d_fileno;
        !           619:                        dp->d_namlen = dt->d_namlen;
        !           620:                        dp->d_type = DT_UNKNOWN;
        !           621:                        dp->d_reclen = dt->d_reclen;
        !           622:                        bcopy(dt->d_name, dp->d_name, dp->d_namlen+1);
        !           623:                        error = uiomove((caddr_t) dp, UIO_MX, uio);
        !           624:                        if (error)
        !           625:                                break;
        !           626:                }
        !           627:                uio->uio_offset = i * UIO_MX;
        !           628:                return (error);
        !           629:        }
        !           630: 
        !           631:        i = uio->uio_offset / UIO_MX;
        !           632:        error = 0;
        !           633:        while (uio->uio_resid > 0) {
        !           634:                if (i >= p->p_fd->fd_nfiles)
        !           635:                        break;
        !           636: 
        !           637:                if (*fdfile(p, i) != NULL && !(*fdflags(p, i) & UF_RESERVED)) {
        !           638:                        struct dirent d;
        !           639:                        struct dirent *dp = &d;
        !           640: 
        !           641:                        bzero((caddr_t) dp, UIO_MX);
        !           642: 
        !           643:                        dp->d_namlen = sprintf(dp->d_name, "%d", i);
        !           644:                        dp->d_reclen = UIO_MX;
        !           645:                        dp->d_type = DT_UNKNOWN;
        !           646:                        dp->d_fileno = i + FD_STDIN;
        !           647:                        /*
        !           648:                         * And ship to userland
        !           649:                         */
        !           650:                        error = uiomove((caddr_t) dp, UIO_MX, uio);
        !           651:                        if (error)
        !           652:                                break;
        !           653:                }
        !           654:                i++;
        !           655:        }
        !           656: 
        !           657:        uio->uio_offset = i * UIO_MX;
        !           658:        return (error);
        !           659: }
        !           660: 
        !           661: int
        !           662: fdesc_readlink(ap)
        !           663:        struct vop_readlink_args /* {
        !           664:                struct vnode *a_vp;
        !           665:                struct uio *a_uio;
        !           666:                struct ucred *a_cred;
        !           667:        } */ *ap;
        !           668: {
        !           669:        struct vnode *vp = ap->a_vp;
        !           670:        int error;
        !           671: 
        !           672:        if (vp->v_type != VLNK)
        !           673:                return (EPERM);
        !           674: 
        !           675:        if (VTOFDESC(vp)->fd_type == Flink) {
        !           676:                char *ln = VTOFDESC(vp)->fd_link;
        !           677:                error = uiomove(ln, strlen(ln), ap->a_uio);
        !           678:        } else {
        !           679:                error = EOPNOTSUPP;
        !           680:        }
        !           681: 
        !           682:        return (error);
        !           683: }
        !           684: 
        !           685: int
        !           686: fdesc_read(ap)
        !           687:        struct vop_read_args /* {
        !           688:                struct vnode *a_vp;
        !           689:                struct uio *a_uio;
        !           690:                int  a_ioflag;
        !           691:                struct ucred *a_cred;
        !           692:        } */ *ap;
        !           693: {
        !           694:        int error = EOPNOTSUPP;
        !           695: 
        !           696:        switch (VTOFDESC(ap->a_vp)->fd_type) {
        !           697:        case Fctty:
        !           698:                error = cttyread(devctty, ap->a_uio, ap->a_ioflag);
        !           699:                break;
        !           700: 
        !           701:        default:
        !           702:                error = EOPNOTSUPP;
        !           703:                break;
        !           704:        }
        !           705:        
        !           706:        return (error);
        !           707: }
        !           708: 
        !           709: int
        !           710: fdesc_write(ap)
        !           711:        struct vop_write_args /* {
        !           712:                struct vnode *a_vp;
        !           713:                struct uio *a_uio;
        !           714:                int  a_ioflag;
        !           715:                struct ucred *a_cred;
        !           716:        } */ *ap;
        !           717: {
        !           718:        int error = EOPNOTSUPP;
        !           719: 
        !           720:        switch (VTOFDESC(ap->a_vp)->fd_type) {
        !           721:        case Fctty:
        !           722:                error = cttywrite(devctty, ap->a_uio, ap->a_ioflag);
        !           723:                break;
        !           724: 
        !           725:        default:
        !           726:                error = EOPNOTSUPP;
        !           727:                break;
        !           728:        }
        !           729:        
        !           730:        return (error);
        !           731: }
        !           732: 
        !           733: int
        !           734: fdesc_ioctl(ap)
        !           735:        struct vop_ioctl_args /* {
        !           736:                struct vnode *a_vp;
        !           737:                int  a_command;
        !           738:                caddr_t  a_data;
        !           739:                int  a_fflag;
        !           740:                struct ucred *a_cred;
        !           741:                struct proc *a_p;
        !           742:        } */ *ap;
        !           743: {
        !           744:        int error = EOPNOTSUPP;
        !           745: 
        !           746:        switch (VTOFDESC(ap->a_vp)->fd_type) {
        !           747:        case Fctty:
        !           748:                error = cttyioctl(devctty, ap->a_command, ap->a_data,
        !           749:                                        ap->a_fflag, ap->a_p);
        !           750:                break;
        !           751: 
        !           752:        default:
        !           753:                error = EOPNOTSUPP;
        !           754:                break;
        !           755:        }
        !           756:        
        !           757:        return (error);
        !           758: }
        !           759: 
        !           760: int
        !           761: fdesc_select(ap)
        !           762:        struct vop_select_args /* {
        !           763:                struct vnode *a_vp;
        !           764:                int  a_which;
        !           765:                int  a_fflags;
        !           766:                struct ucred *a_cred;
        !           767:                struct proc *a_p;
        !           768:        } */ *ap;
        !           769: {
        !           770:        int error = EOPNOTSUPP;
        !           771: 
        !           772:        switch (VTOFDESC(ap->a_vp)->fd_type) {
        !           773:        case Fctty:
        !           774:                error = cttyselect(devctty, ap->a_fflags, ap->a_p);
        !           775:                break;
        !           776: 
        !           777:        default:
        !           778:                error = EOPNOTSUPP;
        !           779:                break;
        !           780:        }
        !           781:        
        !           782:        return (error);
        !           783: }
        !           784: 
        !           785: int
        !           786: fdesc_inactive(ap)
        !           787:        struct vop_inactive_args /* {
        !           788:                struct vnode *a_vp;
        !           789:                struct proc *a_p;
        !           790:        } */ *ap;
        !           791: {
        !           792:        struct vnode *vp = ap->a_vp;
        !           793: 
        !           794:        /*
        !           795:         * Clear out the v_type field to avoid
        !           796:         * nasty things happening in vgone().
        !           797:         */
        !           798:        VOP_UNLOCK(vp, 0, ap->a_p);
        !           799:        vp->v_type = VNON;
        !           800:        return (0);
        !           801: }
        !           802: 
        !           803: int
        !           804: fdesc_reclaim(ap)
        !           805:        struct vop_reclaim_args /* {
        !           806:                struct vnode *a_vp;
        !           807:        } */ *ap;
        !           808: {
        !           809:        struct vnode *vp = ap->a_vp;
        !           810:        struct fdescnode *fd = VTOFDESC(vp);
        !           811: 
        !           812:        LIST_REMOVE(fd, fd_hash);
        !           813:        FREE(vp->v_data, M_TEMP);
        !           814:        vp->v_data = 0;
        !           815: 
        !           816:        return (0);
        !           817: }
        !           818: 
        !           819: /*
        !           820:  * Return POSIX pathconf information applicable to special devices.
        !           821:  */
        !           822: fdesc_pathconf(ap)
        !           823:        struct vop_pathconf_args /* {
        !           824:                struct vnode *a_vp;
        !           825:                int a_name;
        !           826:                int *a_retval;
        !           827:        } */ *ap;
        !           828: {
        !           829: 
        !           830:        switch (ap->a_name) {
        !           831:        case _PC_LINK_MAX:
        !           832:                *ap->a_retval = LINK_MAX;
        !           833:                return (0);
        !           834:        case _PC_MAX_CANON:
        !           835:                *ap->a_retval = MAX_CANON;
        !           836:                return (0);
        !           837:        case _PC_MAX_INPUT:
        !           838:                *ap->a_retval = MAX_INPUT;
        !           839:                return (0);
        !           840:        case _PC_PIPE_BUF:
        !           841:                *ap->a_retval = PIPE_BUF;
        !           842:                return (0);
        !           843:        case _PC_CHOWN_RESTRICTED:
        !           844:                *ap->a_retval = 1;
        !           845:                return (0);
        !           846:        case _PC_VDISABLE:
        !           847:                *ap->a_retval = _POSIX_VDISABLE;
        !           848:                return (0);
        !           849:        default:
        !           850:                return (EINVAL);
        !           851:        }
        !           852:        /* NOTREACHED */
        !           853: }
        !           854: 
        !           855: /*
        !           856:  * Print out the contents of a /dev/fd vnode.
        !           857:  */
        !           858: /* ARGSUSED */
        !           859: int
        !           860: fdesc_print(ap)
        !           861:        struct vop_print_args /* {
        !           862:                struct vnode *a_vp;
        !           863:        } */ *ap;
        !           864: {
        !           865: 
        !           866:        printf("tag VT_NON, fdesc vnode\n");
        !           867:        return (0);
        !           868: }
        !           869: 
        !           870: /*void*/
        !           871: int
        !           872: fdesc_vfree(ap)
        !           873:        struct vop_vfree_args /* {
        !           874:                struct vnode *a_pvp;
        !           875:                ino_t a_ino;
        !           876:                int a_mode;
        !           877:        } */ *ap;
        !           878: {
        !           879: 
        !           880:        return (0);
        !           881: }
        !           882: 
        !           883: /*
        !           884:  * /dev/fd "should never get here" operation
        !           885:  */
        !           886: int
        !           887: fdesc_badop()
        !           888: {
        !           889: 
        !           890:        panic("fdesc: bad op");
        !           891:        /* NOTREACHED */
        !           892: }
        !           893: 
        !           894: /* Pagein  */
        !           895: fdesc_pagein(ap)
        !           896:        struct vop_pagein_args /* {
        !           897:                struct vnode *a_vp;
        !           898:                struct uio *a_uio;
        !           899:                int a_ioflag;
        !           900:                struct ucred *a_cred;
        !           901:        } */ *ap;
        !           902: {
        !           903:        /* pass thru to read */ 
        !           904:        return (VOP_READ(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
        !           905: }
        !           906: 
        !           907: /* Pageout  */
        !           908: fdesc_pageout(ap)
        !           909:        struct vop_pageout_args /* {
        !           910:                struct vnode *a_vp;
        !           911:                struct uio *a_uio;
        !           912:                int a_ioflag;
        !           913:                struct ucred *a_cred;
        !           914:        } */ *ap;
        !           915: {
        !           916:        /* pass thru to write */ 
        !           917:        return (VOP_WRITE(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
        !           918: }
        !           919: 
        !           920: #define fdesc_create ((int (*) __P((struct  vop_create_args *)))eopnotsupp)
        !           921: #define fdesc_mknod ((int (*) __P((struct  vop_mknod_args *)))eopnotsupp)
        !           922: #define fdesc_close ((int (*) __P((struct  vop_close_args *)))nullop)
        !           923: #define fdesc_access ((int (*) __P((struct  vop_access_args *)))nullop)
        !           924: #define fdesc_mmap ((int (*) __P((struct  vop_mmap_args *)))eopnotsupp)
        !           925: #define        fdesc_revoke vop_revoke
        !           926: #define fdesc_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
        !           927: #define fdesc_seek ((int (*) __P((struct  vop_seek_args *)))nullop)
        !           928: #define fdesc_remove ((int (*) __P((struct  vop_remove_args *)))eopnotsupp)
        !           929: #define fdesc_link ((int (*) __P((struct  vop_link_args *)))eopnotsupp)
        !           930: #define fdesc_rename ((int (*) __P((struct  vop_rename_args *)))eopnotsupp)
        !           931: #define fdesc_mkdir ((int (*) __P((struct  vop_mkdir_args *)))eopnotsupp)
        !           932: #define fdesc_rmdir ((int (*) __P((struct  vop_rmdir_args *)))eopnotsupp)
        !           933: #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp)
        !           934: #define fdesc_abortop ((int (*) __P((struct  vop_abortop_args *)))nullop)
        !           935: #define fdesc_lock ((int (*) __P((struct  vop_lock_args *)))vop_nolock)
        !           936: #define fdesc_unlock ((int (*) __P((struct  vop_unlock_args *)))vop_nounlock)
        !           937: #define fdesc_bmap ((int (*) __P((struct  vop_bmap_args *)))fdesc_badop)
        !           938: #define fdesc_strategy ((int (*) __P((struct  vop_strategy_args *)))fdesc_badop)
        !           939: #define fdesc_islocked \
        !           940:        ((int (*) __P((struct vop_islocked_args *)))vop_noislocked)
        !           941: #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp)
        !           942: #define fdesc_blkatoff \
        !           943:        ((int (*) __P((struct  vop_blkatoff_args *)))eopnotsupp)
        !           944: #define fdesc_valloc ((int(*) __P(( \
        !           945:                struct vnode *pvp, \
        !           946:                int mode, \
        !           947:                struct ucred *cred, \
        !           948:                struct vnode **vpp))) eopnotsupp)
        !           949: #define fdesc_truncate \
        !           950:        ((int (*) __P((struct  vop_truncate_args *)))eopnotsupp)
        !           951: #define fdesc_update ((int (*) __P((struct  vop_update_args *)))eopnotsupp)
        !           952: #define fdesc_bwrite ((int (*) __P((struct  vop_bwrite_args *)))eopnotsupp)
        !           953: 
        !           954: int (**fdesc_vnodeop_p)();
        !           955: struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = {
        !           956:        { &vop_default_desc, vn_default_error },
        !           957:        { &vop_lookup_desc, fdesc_lookup },     /* lookup */
        !           958:        { &vop_create_desc, fdesc_create },     /* create */
        !           959:        { &vop_mknod_desc, fdesc_mknod },       /* mknod */
        !           960:        { &vop_open_desc, fdesc_open },         /* open */
        !           961:        { &vop_close_desc, fdesc_close },       /* close */
        !           962:        { &vop_access_desc, fdesc_access },     /* access */
        !           963:        { &vop_getattr_desc, fdesc_getattr },   /* getattr */
        !           964:        { &vop_setattr_desc, fdesc_setattr },   /* setattr */
        !           965:        { &vop_read_desc, fdesc_read },         /* read */
        !           966:        { &vop_write_desc, fdesc_write },       /* write */
        !           967:        { &vop_ioctl_desc, fdesc_ioctl },       /* ioctl */
        !           968:        { &vop_select_desc, fdesc_select },     /* select */
        !           969:        { &vop_revoke_desc, fdesc_revoke },     /* revoke */
        !           970:        { &vop_mmap_desc, fdesc_mmap },         /* mmap */
        !           971:        { &vop_fsync_desc, fdesc_fsync },       /* fsync */
        !           972:        { &vop_seek_desc, fdesc_seek },         /* seek */
        !           973:        { &vop_remove_desc, fdesc_remove },     /* remove */
        !           974:        { &vop_link_desc, fdesc_link },         /* link */
        !           975:        { &vop_rename_desc, fdesc_rename },     /* rename */
        !           976:        { &vop_mkdir_desc, fdesc_mkdir },       /* mkdir */
        !           977:        { &vop_rmdir_desc, fdesc_rmdir },       /* rmdir */
        !           978:        { &vop_symlink_desc, fdesc_symlink },   /* symlink */
        !           979:        { &vop_readdir_desc, fdesc_readdir },   /* readdir */
        !           980:        { &vop_readlink_desc, fdesc_readlink }, /* readlink */
        !           981:        { &vop_abortop_desc, fdesc_abortop },   /* abortop */
        !           982:        { &vop_inactive_desc, fdesc_inactive }, /* inactive */
        !           983:        { &vop_reclaim_desc, fdesc_reclaim },   /* reclaim */
        !           984:        { &vop_lock_desc, fdesc_lock },         /* lock */
        !           985:        { &vop_unlock_desc, fdesc_unlock },     /* unlock */
        !           986:        { &vop_bmap_desc, fdesc_bmap },         /* bmap */
        !           987:        { &vop_strategy_desc, fdesc_strategy }, /* strategy */
        !           988:        { &vop_print_desc, fdesc_print },       /* print */
        !           989:        { &vop_islocked_desc, fdesc_islocked }, /* islocked */
        !           990:        { &vop_pathconf_desc, fdesc_pathconf }, /* pathconf */
        !           991:        { &vop_advlock_desc, fdesc_advlock },   /* advlock */
        !           992:        { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */
        !           993:        { &vop_valloc_desc, fdesc_valloc },     /* valloc */
        !           994:        { &vop_vfree_desc, fdesc_vfree },       /* vfree */
        !           995:        { &vop_truncate_desc, fdesc_truncate }, /* truncate */
        !           996:        { &vop_update_desc, fdesc_update },     /* update */
        !           997:        { &vop_bwrite_desc, fdesc_bwrite },     /* bwrite */
        !           998:        { &vop_bwrite_desc, fdesc_pagein },     /* pagein */
        !           999:        { &vop_bwrite_desc, fdesc_pageout },    /* pageout */
        !          1000:        { (struct vnodeop_desc*)NULL, (int(*)())NULL }
        !          1001: };
        !          1002: struct vnodeopv_desc fdesc_vnodeop_opv_desc =
        !          1003:        { &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.