[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.32

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

CVSweb <webmaster@jp.NetBSD.org>