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