[BACK]Return to fdesc_vnops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / miscfs / fdesc

Annotation of src/sys/miscfs/fdesc/fdesc_vnops.c, Revision 1.1.1.2

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

CVSweb <webmaster@jp.NetBSD.org>