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

1.1       cgd         1: /*
1.8       cgd         2:  * Copyright (c) 1992 The Regents of the University of California
                      3:  * Copyright (c) 1990, 1992, 1993 Jan-Simon Pendry
1.1       cgd         4:  * All rights reserved.
                      5:  *
1.8       cgd         6:  * This code is derived from software donated to Berkeley by
1.1       cgd         7:  * Jan-Simon Pendry.
                      8:  *
1.2       cgd         9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
1.8       cgd        19:  *     This product includes software developed by the University of
                     20:  *     California, Berkeley and its contributors.
1.2       cgd        21:  * 4. Neither the name of the University nor the names of its contributors
                     22:  *    may be used to endorse or promote products derived from this software
                     23:  *    without specific prior written permission.
1.1       cgd        24:  *
1.2       cgd        25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     35:  * SUCH DAMAGE.
1.1       cgd        36:  *
1.8       cgd        37:  * From:
                     38:  *     Id: fdesc_vnops.c,v 4.1 1993/12/17 10:47:45 jsp Rel
                     39:  *
1.9     ! cgd        40:  *     $Id: fdesc_vnops.c,v 1.8 1994/01/05 09:01:02 cgd 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>
                     54: #include <sys/filedesc.h>
                     55: #include <sys/vnode.h>
                     56: #include <sys/file.h>
                     57: #include <sys/stat.h>
                     58: #include <sys/mount.h>
                     59: #include <sys/namei.h>
                     60: #include <sys/buf.h>
                     61: #include <miscfs/fdesc/fdesc.h>
                     62:
                     63: #include <ufs/dir.h>           /* For readdir() XXX */
                     64:
                     65: #define cttyvp(p) ((p)->p_flag&SCTTY ? (p)->p_session->s_ttyvp : NULL)
                     66:
                     67: #define FDL_WANT       0x01
                     68: #define FDL_LOCKED     0x02
                     69: static int fdescvplock;
                     70: static struct vnode *fdescvp[FD_MAX];
                     71:
                     72: #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1)
                     73: FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2
                     74: #endif
                     75:
                     76: fdesc_allocvp(ftype, ix, mp, vpp)
                     77:        fdntype ftype;
                     78:        int ix;
                     79:        struct mount *mp;
                     80:        struct vnode **vpp;
                     81: {
                     82:        struct vnode **nvpp = 0;
                     83:        int error = 0;
                     84:
                     85: loop:
                     86:        /* get stashed copy of the vnode */
                     87:        if (ix >= 0 && ix < FD_MAX) {
                     88:                nvpp = &fdescvp[ix];
                     89:                if (*nvpp) {
                     90:                        if (vget(*nvpp))
                     91:                                goto loop;
                     92:                        VOP_UNLOCK(*nvpp);
                     93:                        *vpp = *nvpp;
                     94:                        return (error);
                     95:                }
                     96:        }
                     97:
                     98:        /*
                     99:         * otherwise lock the array while we call getnewvnode
                    100:         * since that can block.
                    101:         */
                    102:        if (fdescvplock & FDL_LOCKED) {
                    103:                fdescvplock |= FDL_WANT;
                    104:                sleep((caddr_t) &fdescvplock, PINOD);
                    105:                goto loop;
                    106:        }
                    107:        fdescvplock |= FDL_LOCKED;
1.1       cgd       108:
1.9     ! cgd       109:        error = getnewvnode(VT_FDESC, mp, &fdesc_vnodeops, vpp);
1.8       cgd       110:        if (error)
                    111:                goto out;
                    112:        if (nvpp)
                    113:                *nvpp = *vpp;
                    114:        VTOFDESC(*vpp)->fd_type = ftype;
                    115:        VTOFDESC(*vpp)->fd_fd = -1;
                    116:        VTOFDESC(*vpp)->fd_link = 0;
                    117:        VTOFDESC(*vpp)->fd_ix = ix;
                    118:
                    119: out:;
                    120:        fdescvplock &= ~FDL_LOCKED;
                    121:
                    122:        if (fdescvplock & FDL_WANT) {
                    123:                fdescvplock &= ~FDL_WANT;
                    124:                wakeup((caddr_t) &fdescvplock);
                    125:        }
                    126:
                    127:        return (error);
                    128: }
1.1       cgd       129:
                    130: /*
                    131:  * vp is the current namei directory
                    132:  * ndp is the name to locate in that directory...
                    133:  */
                    134: fdesc_lookup(dvp, ndp, p)
                    135:        struct vnode *dvp;
                    136:        struct nameidata *ndp;
                    137:        struct proc *p;
                    138: {
                    139:        char *pname = ndp->ni_ptr;
                    140:        int nfiles = p->p_fd->fd_nfiles;
                    141:        unsigned fd;
                    142:        int error;
                    143:        struct vnode *fvp;
1.8       cgd       144:        char *ln;
1.1       cgd       145:
                    146: #ifdef FDESC_DIAGNOSTIC
                    147:        printf("fdesc_lookup(%s)\n", pname);
                    148: #endif
                    149:        if (ndp->ni_namelen == 1 && *pname == '.') {
                    150:                ndp->ni_dvp = dvp;
                    151:                ndp->ni_vp = dvp;
                    152:                VREF(dvp);
1.8       cgd       153:                VOP_LOCK(dvp);
1.1       cgd       154:                return (0);
                    155:        }
                    156:
1.8       cgd       157:        switch (VTOFDESC(dvp)->fd_type) {
                    158:        default:
                    159:        case Flink:
                    160:        case Fdesc:
                    161:        case Fctty:
                    162:                error = ENOTDIR;
                    163:                goto bad;
                    164:
                    165:        case Froot:
                    166:                if (ndp->ni_namelen == 2 && bcmp(pname, "fd", 2) == 0) {
                    167:                        error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp);
                    168:                        if (error)
                    169:                                goto bad;
                    170:                        ndp->ni_dvp = dvp;
                    171:                        ndp->ni_vp = fvp;
                    172:                        fvp->v_type = VDIR;
                    173:                        VOP_LOCK(fvp);
                    174: #ifdef FDESC_DIAGNOSTIC
                    175:                        printf("fdesc_lookup: newvp = %x\n", fvp);
                    176: #endif
                    177:                        return (0);
                    178:                }
                    179:
                    180:                if (ndp->ni_namelen == 3 && bcmp(pname, "tty", 3) == 0) {
                    181:                        struct vnode *ttyvp = cttyvp(p);
                    182:                        if (ttyvp == NULL) {
                    183:                                error = ENXIO;
                    184:                                goto bad;
                    185:                        }
                    186:                        error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp);
                    187:                        if (error)
                    188:                                goto bad;
                    189:                        ndp->ni_dvp = dvp;
                    190:                        ndp->ni_vp = fvp;
                    191:                        fvp->v_type = VFIFO;
                    192:                        VOP_LOCK(fvp);
                    193: #ifdef FDESC_DIAGNOSTIC
                    194:                        printf("fdesc_lookup: ttyvp = %x\n", fvp);
                    195: #endif
                    196:                        return (0);
                    197:                }
                    198:
                    199:                ln = 0;
                    200:                switch (ndp->ni_namelen) {
                    201:                case 5:
                    202:                        if (bcmp(pname, "stdin", 5) == 0) {
                    203:                                ln = "fd/0";
                    204:                                fd = FD_STDIN;
                    205:                        }
1.1       cgd       206:                        break;
1.8       cgd       207:                case 6:
                    208:                        if (bcmp(pname, "stdout", 6) == 0) {
                    209:                                ln = "fd/1";
                    210:                                fd = FD_STDOUT;
                    211:                        } else
                    212:                        if (bcmp(pname, "stderr", 6) == 0) {
                    213:                                ln = "fd/2";
                    214:                                fd = FD_STDERR;
                    215:                        }
                    216:                        break;
                    217:                }
                    218:
                    219:                if (ln) {
                    220: #ifdef FDESC_DIAGNOSTIC
                    221:                        printf("fdesc_lookup: link -> %s\n", ln);
                    222: #endif
                    223:                        error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp);
                    224:                        if (error)
                    225:                                goto bad;
                    226:                        VTOFDESC(fvp)->fd_link = ln;
                    227:                        ndp->ni_dvp = dvp;
                    228:                        ndp->ni_vp = fvp;
                    229:                        fvp->v_type = VLNK;
                    230:                        VOP_LOCK(fvp);
                    231: #ifdef FDESC_DIAGNOSTIC
                    232:                        printf("fdesc_lookup: newvp = %x\n", fvp);
                    233: #endif
                    234:                        return (0);
                    235:                } else {
                    236:                        error = ENOENT;
                    237:                        goto bad;
                    238:                }
                    239:
                    240:                /* fall through */
                    241:
                    242:        case Fdevfd:
                    243:                if (ndp->ni_namelen == 2 && bcmp(pname, "..", 2) == 0) {
                    244:                        ndp->ni_dvp = dvp;
                    245:                        error = fdesc_root(dvp->v_mount, &ndp->ni_vp);
                    246:                        return (error);
                    247:                }
                    248:
                    249:                fd = 0;
                    250:                while (*pname >= '0' && *pname <= '9') {
                    251:                        fd = 10 * fd + *pname++ - '0';
                    252:                        if (fd >= nfiles)
                    253:                                break;
                    254:                }
1.1       cgd       255:
                    256: #ifdef FDESC_DIAGNOSTIC
1.8       cgd       257:                printf("fdesc_lookup: fd = %d, *pname = %x\n", fd, *pname);
1.1       cgd       258: #endif
1.8       cgd       259:                if (*pname == '/') {
                    260:                        error = ENOTDIR;
                    261:                        goto bad;
                    262:                }
1.1       cgd       263:
1.8       cgd       264:                if (*pname != '\0') {
                    265:                        error = ENOENT;
                    266:                        goto bad;
                    267:                }
1.1       cgd       268:
1.8       cgd       269: devfd:
                    270:                if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) {
                    271:                        error = EBADF;
                    272:                        goto bad;
                    273:                }
1.1       cgd       274:
                    275: #ifdef FDESC_DIAGNOSTIC
1.8       cgd       276:                printf("fdesc_lookup: allocate new vnode\n");
1.1       cgd       277: #endif
1.8       cgd       278:                error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp);
                    279:                if (error)
                    280:                        goto bad;
                    281:                VTOFDESC(fvp)->fd_fd = fd;
                    282:                ndp->ni_dvp = dvp;
                    283:                ndp->ni_vp = fvp;
1.1       cgd       284: #ifdef FDESC_DIAGNOSTIC
1.8       cgd       285:                printf("fdesc_lookup: newvp = %x\n", fvp);
1.1       cgd       286: #endif
1.8       cgd       287:                return (0);
                    288:        }
1.1       cgd       289:
                    290: bad:;
                    291:        ndp->ni_dvp = dvp;
                    292:        ndp->ni_vp = NULL;
                    293: #ifdef FDESC_DIAGNOSTIC
                    294:        printf("fdesc_lookup: error = %d\n", error);
                    295: #endif
                    296:        return (error);
                    297: }
                    298:
                    299: fdesc_open(vp, mode, cred, p)
                    300:        struct vnode *vp;
                    301:        int mode;
                    302:        struct ucred *cred;
                    303:        struct proc *p;
                    304: {
1.8       cgd       305:        int error = 0;
                    306:
                    307:        switch (VTOFDESC(vp)->fd_type) {
                    308:        case Fdesc:
                    309:                /*
                    310:                 * XXX Kludge: set p->p_dupfd to contain the value of the
                    311:                 * the file descriptor being sought for duplication. The error
                    312:                 * return ensures that the vnode for this device will be
                    313:                 * released by vn_open. Open will detect this special error and
                    314:                 * take the actions in dupfdopen.  Other callers of vn_open or
                    315:                 * VOP_OPEN will simply report the error.
                    316:                 */
                    317:                p->p_dupfd = VTOFDESC(vp)->fd_fd;       /* XXX */
                    318:                error = ENODEV;
                    319:                break;
1.1       cgd       320:
1.8       cgd       321:        case Fctty:
                    322:                error = cttyopen(devctty, mode, 0, p);
                    323:                break;
                    324:        }
1.1       cgd       325:
1.8       cgd       326:        return (error);
1.1       cgd       327: }
                    328:
                    329: static int
                    330: fdesc_attr(fd, vap, cred, p)
                    331:        int fd;
                    332:        struct vattr *vap;
                    333:        struct ucred *cred;
                    334:        struct proc *p;
                    335: {
                    336:        struct filedesc *fdp = p->p_fd;
                    337:        struct file *fp;
1.8       cgd       338:        struct stat stb;
1.1       cgd       339:        int error;
                    340:
                    341: #ifdef FDESC_DIAGNOSTIC
                    342:        printf("fdesc_attr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles);
                    343: #endif
                    344:        if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) {
                    345: #ifdef FDESC_DIAGNOSTIC
                    346:                printf("fdesc_attr: fp = %x (EBADF)\n", fp);
                    347: #endif
                    348:                return (EBADF);
                    349:        }
                    350:
                    351:        /*
                    352:         * Can stat the underlying vnode, but not sockets because
                    353:         * they don't use struct vattrs.  Well, we could convert from
                    354:         * a struct stat back to a struct vattr, later...
                    355:         */
                    356:        switch (fp->f_type) {
                    357:        case DTYPE_VNODE:
                    358:                error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p);
1.8       cgd       359:                if (error == 0 && vap->va_type == VDIR) {
                    360:                        /*
                    361:                         * don't allow directories to show up because
                    362:                         * that causes loops in the namespace.
                    363:                         */
                    364:                        vap->va_type = VFIFO;
                    365:                }
1.1       cgd       366:                break;
                    367:
                    368:        case DTYPE_SOCKET:
1.8       cgd       369:                error = soo_stat((struct socket *)fp->f_data, &stb);
                    370:                if (error == 0) {
                    371:                        vattr_null(vap);
                    372:                        vap->va_type = VSOCK;
                    373:                        vap->va_mode = stb.st_mode;
                    374:                        vap->va_nlink = stb.st_nlink;
                    375:                        vap->va_uid = stb.st_uid;
                    376:                        vap->va_gid = stb.st_gid;
                    377:                        vap->va_fsid = stb.st_dev;
                    378:                        vap->va_fileid = stb.st_ino;
                    379:                        vap->va_size = stb.st_size;
                    380:                        vap->va_blocksize = stb.st_blksize;
                    381:                        vap->va_atime.tv_sec = stb.st_atime;
                    382:                        vap->va_atime.tv_usec = 0;
                    383:                        vap->va_mtime.tv_sec = stb.st_mtime;
                    384:                        vap->va_mtime.tv_usec = 0;
                    385:                        vap->va_ctime.tv_sec = stb.st_ctime;
                    386:                        vap->va_ctime.tv_usec = 0;
                    387:                        vap->va_gen = stb.st_gen;
                    388:                        vap->va_flags = stb.st_flags;
                    389:                        vap->va_rdev = stb.st_rdev;
                    390:                        vap->va_bytes = stb.st_blocks * stb.st_blksize;
                    391:                }
1.1       cgd       392:                break;
                    393:
                    394:        default:
                    395:                panic("fdesc attr");
                    396:                break;
                    397:        }
                    398:
                    399: #ifdef FDESC_DIAGNOSTIC
                    400:        printf("fdesc_attr: returns error %d\n", error);
                    401: #endif
                    402:        return (error);
                    403: }
                    404:
                    405: fdesc_getattr(vp, vap, cred, p)
                    406:        struct vnode *vp;
                    407:        struct vattr *vap;
                    408:        struct ucred *cred;
                    409:        struct proc *p;
                    410: {
                    411:        unsigned fd;
1.8       cgd       412:        int error = 0;
1.1       cgd       413:
                    414: #ifdef FDESC_DIAGNOSTIC
1.8       cgd       415:        printf("fdesc_getattr: stat type = %d\n", VTOFDESC(vp)->fd_type);
1.1       cgd       416: #endif
1.8       cgd       417:
                    418:        switch (VTOFDESC(vp)->fd_type) {
                    419:        case Froot:
                    420:        case Fdevfd:
                    421:        case Flink:
                    422:        case Fctty:
1.1       cgd       423:                bzero((caddr_t) vap, sizeof(*vap));
                    424:                vattr_null(vap);
1.8       cgd       425:                vap->va_fileid = VTOFDESC(vp)->fd_ix;
                    426:
                    427:                switch (VTOFDESC(vp)->fd_type) {
                    428:                case Flink:
                    429:                        vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
                    430:                        vap->va_type = VLNK;
                    431:                        vap->va_nlink = 1;
                    432:                        /* vap->va_qsize = strlen(VTOFDESC(vp)->fd_link); */
                    433:                        vap->va_size = strlen(VTOFDESC(vp)->fd_link);
                    434:                        break;
                    435:
                    436:                case Fctty:
                    437:                        vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
                    438:                        vap->va_type = VFIFO;
                    439:                        vap->va_nlink = 1;
                    440:                        /* vap->va_qsize = 0; */
                    441:                        vap->va_size = 0;
                    442:                        break;
                    443:
                    444:                default:
                    445:                        vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH;
                    446:                        vap->va_type = VDIR;
                    447:                        vap->va_nlink = 2;
                    448:                        /* vap->va_qsize = 0; */
                    449:                        vap->va_size = DEV_BSIZE;
                    450:                        break;
                    451:                }
1.1       cgd       452:                vap->va_uid = 0;
                    453:                vap->va_gid = 0;
                    454:                vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
                    455:                vap->va_blocksize = DEV_BSIZE;
1.8       cgd       456:                vap->va_atime.tv_sec = boottime.tv_sec;
                    457:                vap->va_atime.tv_usec = 0;
1.1       cgd       458:                vap->va_mtime = vap->va_atime;
                    459:                vap->va_ctime = vap->va_ctime;
                    460:                vap->va_gen = 0;
                    461:                vap->va_flags = 0;
                    462:                vap->va_rdev = 0;
                    463:                /* vap->va_qbytes = 0; */
                    464:                vap->va_bytes = 0;
1.8       cgd       465:                break;
                    466:
                    467:        case Fdesc:
                    468: #ifdef FDESC_DIAGNOSTIC
                    469:                printf("fdesc_getattr: stat desc #%d\n", VTOFDESC(vp)->fd_fd);
                    470: #endif
                    471:                fd = VTOFDESC(vp)->fd_fd;
                    472:                error = fdesc_attr(fd, vap, cred, p);
                    473:                break;
                    474:
                    475:        default:
                    476:                panic("fdesc_getattr");
                    477:                break;
1.1       cgd       478:        }
                    479:
                    480:        if (error == 0)
                    481:                vp->v_type = vap->va_type;
1.8       cgd       482:
                    483: #ifdef FDESC_DIAGNOSTIC
                    484:        printf("fdesc_getattr: stat returns 0\n");
                    485: #endif
1.1       cgd       486:        return (error);
                    487: }
                    488:
                    489: fdesc_setattr(vp, vap, cred, p)
                    490:        struct vnode *vp;
                    491:        struct vattr *vap;
                    492:        struct ucred *cred;
                    493:        struct proc *p;
                    494: {
                    495:        struct filedesc *fdp = p->p_fd;
                    496:        struct file *fp;
                    497:        unsigned fd;
                    498:        int error;
                    499:
                    500:        /*
                    501:         * Can't mess with the root vnode
                    502:         */
1.8       cgd       503:        switch (VTOFDESC(vp)->fd_type) {
                    504:        case Fdesc:
                    505:                break;
                    506:
                    507:        case Fctty:
                    508:                return (0);
                    509:
                    510:        default:
1.1       cgd       511:                return (EACCES);
1.8       cgd       512:        }
1.1       cgd       513:
1.8       cgd       514:        fd = VTOFDESC(vp)->fd_fd;
1.1       cgd       515: #ifdef FDESC_DIAGNOSTIC
                    516:        printf("fdesc_setattr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles);
                    517: #endif
                    518:        if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) {
                    519: #ifdef FDESC_DIAGNOSTIC
                    520:                printf("fdesc_setattr: fp = %x (EBADF)\n", fp);
                    521: #endif
                    522:                return (EBADF);
                    523:        }
                    524:
                    525:        /*
                    526:         * Can setattr the underlying vnode, but not sockets!
                    527:         */
                    528:        switch (fp->f_type) {
                    529:        case DTYPE_VNODE:
                    530:                error = VOP_SETATTR((struct vnode *) fp->f_data, vap, cred, p);
                    531:                break;
                    532:
                    533:        case DTYPE_SOCKET:
1.8       cgd       534:                error = 0; /* EOPNOTSUPP? */
1.1       cgd       535:                break;
                    536:
                    537:        default:
                    538:                panic("fdesc setattr");
                    539:                break;
                    540:        }
                    541:
                    542: #ifdef FDESC_DIAGNOSTIC
                    543:        printf("fdesc_setattr: returns error %d\n", error);
                    544: #endif
                    545:        return (error);
                    546: }
                    547:
1.8       cgd       548: #define UIO_MX 16
                    549:
                    550: static struct dirtmp {
                    551:        u_long d_ino;
                    552:        u_short d_reclen;
                    553:        u_short d_namlen;
                    554:        char d_name[8];
                    555: } rootent[] = {
                    556:        { FD_DEVFD, UIO_MX, 2, "fd" },
                    557:        { FD_STDIN, UIO_MX, 5, "stdin" },
                    558:        { FD_STDOUT, UIO_MX, 6, "stdout" },
                    559:        { FD_STDERR, UIO_MX, 6, "stderr" },
                    560:        { FD_CTTY, UIO_MX, 3, "tty" },
                    561:        { 0 }
                    562: };
                    563:
1.6       ws        564: fdesc_readdir(vp, uio, cred, eofflagp, cookies, ncookies)
1.1       cgd       565:        struct vnode *vp;
                    566:        struct uio *uio;
                    567:        struct ucred *cred;
                    568:        int *eofflagp;
1.6       ws        569:        u_int *cookies;
                    570:        int ncookies;
1.1       cgd       571: {
                    572:        struct filedesc *fdp;
1.8       cgd       573:        int i;
1.1       cgd       574:        int error;
                    575:
1.8       cgd       576:        switch (VTOFDESC(vp)->fd_type) {
                    577:        case Fctty:
                    578:                return (0);
                    579:
                    580:        case Fdesc:
                    581:                return (ENOTDIR);
                    582:
                    583:        default:
                    584:                break;
                    585:        }
1.1       cgd       586:
                    587:        fdp = uio->uio_procp->p_fd;
1.8       cgd       588:
                    589:        if (VTOFDESC(vp)->fd_type == Froot) {
1.3       cgd       590:                struct direct d;
                    591:                struct direct *dp = &d;
1.8       cgd       592:                struct dirtmp *dt;
                    593:
                    594:                i = uio->uio_offset / UIO_MX;
                    595:                error = 0;
1.3       cgd       596:
1.8       cgd       597:                while (uio->uio_resid > 0) {
                    598:                        dt = &rootent[i];
                    599:                        if (dt->d_ino == 0) {
                    600:                                *eofflagp = 1;
                    601:                                break;
                    602:                        }
                    603:                        i++;
                    604:
                    605:                        switch (dt->d_ino) {
                    606:                        case FD_CTTY:
                    607:                                if (cttyvp(uio->uio_procp) == NULL)
                    608:                                        continue;
                    609:                                break;
                    610:
                    611:                        case FD_STDIN:
                    612:                        case FD_STDOUT:
                    613:                        case FD_STDERR:
                    614:                                if ((dt->d_ino-FD_STDIN) >= fdp->fd_nfiles)
                    615:                                        continue;
                    616:                                if (fdp->fd_ofiles[dt->d_ino-FD_STDIN] == NULL)
                    617:                                        continue;
                    618:                                break;
                    619:                        }
                    620:                        bzero(dp, UIO_MX);
                    621:                        dp->d_ino = dt->d_ino;
                    622:                        dp->d_namlen = dt->d_namlen;
                    623:                        dp->d_reclen = dt->d_reclen;
                    624:                        bcopy(dt->d_name, dp->d_name, dp->d_namlen+1);
                    625:                        error = uiomove((caddr_t) dp, UIO_MX, uio);
                    626:                        if (error)
                    627:                                break;
1.3       cgd       628:                }
1.8       cgd       629:                uio->uio_offset = i * UIO_MX;
                    630:                return (error);
                    631:        }
                    632:
                    633:        i = uio->uio_offset / UIO_MX;
                    634:        error = 0;
                    635:        while (uio->uio_resid > 0) {
1.1       cgd       636:                if (i >= fdp->fd_nfiles) {
                    637:                        *eofflagp = 1;
                    638:                        break;
                    639:                }
                    640:                if (fdp->fd_ofiles[i] != NULL) {
                    641:                        struct direct d;
                    642:                        struct direct *dp = &d;
                    643: #ifdef FDESC_FILEID
                    644:                        struct vattr va;
                    645: #endif
                    646:                        bzero((caddr_t) dp, UIO_MX);
                    647:
1.8       cgd       648:                        dp->d_namlen = sprintf(dp->d_name, "%d", i);
1.1       cgd       649:                        /*
                    650:                         * Fill in the remaining fields
                    651:                         */
                    652:                        dp->d_reclen = UIO_MX;
1.8       cgd       653:                        dp->d_ino = i + FD_STDIN;
1.1       cgd       654: #ifdef FDESC_FILEID
                    655:                        /*
                    656:                         * If we want the file ids to match the
                    657:                         * we must call getattr on the underlying file.
                    658:                         * fdesc_attr may return an error, in which case
                    659:                         * we ignore the returned file id.
                    660:                         */
                    661:                        error = fdesc_attr(i, &va, cred, p);
                    662:                        if (error == 0)
                    663:                                dp->d_ino = va.va_fileid;
                    664: #endif
                    665:                        /*
                    666:                         * And ship to userland
                    667:                         */
                    668:                        error = uiomove((caddr_t) dp, UIO_MX, uio);
                    669:                        if (error)
                    670:                                break;
                    671:                }
1.8       cgd       672:                i++;
                    673:        }
                    674:
                    675:        uio->uio_offset = i * UIO_MX;
                    676:        return (error);
                    677: }
                    678:
                    679: fdesc_readlink(vp, uio, cred)
                    680:        struct vnode *vp;
                    681:        struct uio *uio;
                    682:        struct ucred *cred;
                    683: {
                    684:        int error;
                    685:
                    686:        if (VTOFDESC(vp)->fd_type == Flink) {
                    687:                char *ln = VTOFDESC(vp)->fd_link;
                    688:                error = uiomove(ln, strlen(ln), uio);
                    689:        } else {
                    690:                error = EOPNOTSUPP;
                    691:        }
                    692:
                    693:        return (error);
                    694: }
                    695:
                    696: fdesc_read(vp, uio, ioflag, cred)
                    697:        struct vnode *vp;
                    698:        struct uio *uio;
                    699:        int ioflag;
                    700:        struct ucred *cred;
                    701: {
                    702:        int error = EOPNOTSUPP;
                    703:
                    704:        switch (VTOFDESC(vp)->fd_type) {
                    705:        case Fctty:
                    706:                error = cttyread(devctty, uio, ioflag);
                    707:                break;
                    708:
                    709:        default:
                    710:                error = EOPNOTSUPP;
                    711:                break;
                    712:        }
                    713:
                    714:        return (error);
                    715: }
                    716:
                    717: fdesc_write(vp, uio, ioflag, cred)
                    718:        struct vnode *vp;
                    719:        struct uio *uio;
                    720:        int ioflag;
                    721:        struct ucred *cred;
                    722: {
                    723:        int error = EOPNOTSUPP;
                    724:
                    725:        switch (VTOFDESC(vp)->fd_type) {
                    726:        case Fctty:
                    727:                error = cttywrite(devctty, uio, ioflag);
                    728:                break;
                    729:
                    730:        default:
                    731:                error = EOPNOTSUPP;
                    732:                break;
                    733:        }
                    734:
                    735:        return (error);
                    736: }
                    737:
                    738: fdesc_ioctl(vp, command, data, fflag, cred, p)
                    739:        struct vnode *vp;
                    740:        int command;
                    741:        caddr_t data;
                    742:        int fflag;
                    743:        struct ucred *cred;
                    744:        struct proc *p;
                    745: {
                    746:        int error = EOPNOTSUPP;
                    747:
                    748: #ifdef FDESC_DIAGNOSTIC
                    749:        printf("fdesc_ioctl: type = %d, command = %x\n",
                    750:                        VTOFDESC(vp)->fd_type, command);
                    751: #endif
                    752:        switch (VTOFDESC(vp)->fd_type) {
                    753:        case Fctty:
                    754:                error = cttyioctl(devctty, command, data, fflag, p);
                    755:                break;
                    756:
                    757:        default:
                    758:                error = EOPNOTSUPP;
                    759:                break;
1.1       cgd       760:        }
1.8       cgd       761:
                    762:        return (error);
                    763: }
                    764:
                    765: fdesc_select(vp, which, fflags, cred, p)
                    766:        struct vnode *vp;
                    767:        int which;
                    768:        int fflags;
                    769:        struct ucred *cred;
                    770:        struct proc *p;
                    771: {
                    772:        int error = EOPNOTSUPP;
                    773:
                    774:        switch (VTOFDESC(vp)->fd_type) {
                    775:        case Fctty:
                    776:                error = cttyselect(devctty, fflags, p);
                    777:                break;
1.1       cgd       778:
1.8       cgd       779:        default:
                    780:                error = EOPNOTSUPP;
                    781:                break;
                    782:        }
                    783:
1.1       cgd       784:        return (error);
1.8       cgd       785:
1.1       cgd       786: }
                    787:
                    788: fdesc_inactive(vp, p)
                    789:        struct vnode *vp;
                    790:        struct proc *p;
                    791: {
                    792:        /*
                    793:         * Clear out the v_type field to avoid
                    794:         * nasty things happening in vgone().
                    795:         */
                    796:        vp->v_type = VNON;
                    797: #ifdef FDESC_DIAGNOSTIC
                    798:        printf("fdesc_inactive(%x)\n", vp);
                    799: #endif
                    800:        return (0);
                    801: }
                    802:
1.8       cgd       803: int fdesc_reclaim(vp)
                    804: struct vnode *vp;
                    805: {
                    806:        int ix;
                    807:
                    808: #ifdef FDESC_DIAGNOSTIC
                    809:        printf("fdesc_reclaim(%x)\n", vp);
                    810: #endif
                    811:
                    812:        ix = VTOFDESC(vp)->fd_ix;
                    813:        if (ix >= 0 && ix < FD_MAX) {
                    814:                if (fdescvp[ix] != vp)
                    815:                        panic("fdesc_reclaim");
                    816:                fdescvp[ix] = 0;
                    817:        }
                    818:        return (0);
                    819: }
                    820:
1.1       cgd       821: /*
                    822:  * Print out the contents of a /dev/fd vnode.
                    823:  */
                    824: /* ARGSUSED */
                    825: fdesc_print(vp)
                    826:        struct vnode *vp;
                    827: {
1.8       cgd       828:        printf("tag VT_NON, fdesc vnode\n");
1.1       cgd       829: }
                    830:
                    831: /*
                    832:  * /dev/fd vnode unsupported operation
                    833:  */
                    834: fdesc_enotsupp()
                    835: {
                    836:        return (EOPNOTSUPP);
                    837: }
                    838:
                    839: /*
                    840:  * /dev/fd "should never get here" operation
                    841:  */
                    842: fdesc_badop()
                    843: {
                    844:        panic("fdesc: bad op");
                    845:        /* NOTREACHED */
                    846: }
                    847:
                    848: /*
                    849:  * /dev/fd vnode null operation
                    850:  */
                    851: fdesc_nullop()
                    852: {
                    853:        return (0);
                    854: }
                    855:
                    856: #define fdesc_create ((int (*) __P(( \
                    857:                struct nameidata *ndp, \
                    858:                struct vattr *vap, \
                    859:                struct proc *p))) fdesc_enotsupp)
                    860: #define fdesc_mknod ((int (*) __P(( \
                    861:                struct nameidata *ndp, \
                    862:                struct vattr *vap, \
                    863:                struct ucred *cred, \
                    864:                struct proc *p))) fdesc_enotsupp)
                    865: #define fdesc_close ((int (*) __P(( \
                    866:                struct vnode *vp, \
                    867:                int fflag, \
                    868:                struct ucred *cred, \
                    869:                struct proc *p))) nullop)
                    870: #define fdesc_access ((int (*) __P(( \
                    871:                struct vnode *vp, \
                    872:                int mode, \
                    873:                struct ucred *cred, \
                    874:                struct proc *p))) nullop)
                    875: #define fdesc_mmap ((int (*) __P(( \
                    876:                struct vnode *vp, \
                    877:                int fflags, \
                    878:                struct ucred *cred, \
                    879:                struct proc *p))) fdesc_enotsupp)
                    880: #define fdesc_fsync ((int (*) __P(( \
                    881:                struct vnode *vp, \
                    882:                int fflags, \
                    883:                struct ucred *cred, \
                    884:                int waitfor, \
                    885:                struct proc *p))) nullop)
                    886: #define fdesc_seek ((int (*) __P(( \
                    887:                struct vnode *vp, \
                    888:                off_t oldoff, \
                    889:                off_t newoff, \
                    890:                struct ucred *cred))) nullop)
                    891: #define fdesc_remove ((int (*) __P(( \
                    892:                struct nameidata *ndp, \
                    893:                struct proc *p))) fdesc_enotsupp)
                    894: #define fdesc_link ((int (*) __P(( \
                    895:                struct vnode *vp, \
                    896:                struct nameidata *ndp, \
                    897:                struct proc *p))) fdesc_enotsupp)
                    898: #define fdesc_rename ((int (*) __P(( \
                    899:                struct nameidata *fndp, \
                    900:                struct nameidata *tdnp, \
                    901:                struct proc *p))) fdesc_enotsupp)
                    902: #define fdesc_mkdir ((int (*) __P(( \
                    903:                struct nameidata *ndp, \
                    904:                struct vattr *vap, \
                    905:                struct proc *p))) fdesc_enotsupp)
                    906: #define fdesc_rmdir ((int (*) __P(( \
                    907:                struct nameidata *ndp, \
                    908:                struct proc *p))) fdesc_enotsupp)
                    909: #define fdesc_symlink ((int (*) __P(( \
                    910:                struct nameidata *ndp, \
                    911:                struct vattr *vap, \
                    912:                char *target, \
                    913:                struct proc *p))) fdesc_enotsupp)
                    914: #define fdesc_abortop ((int (*) __P(( \
                    915:                struct nameidata *ndp))) nullop)
                    916: #define        fdesc_lock ((int (*) __P(( \
                    917:                struct vnode *vp))) nullop)
                    918: #define fdesc_unlock ((int (*) __P(( \
                    919:                struct vnode *vp))) nullop)
                    920: #define        fdesc_bmap ((int (*) __P(( \
                    921:                struct vnode *vp, \
                    922:                daddr_t bn, \
                    923:                struct vnode **vpp, \
                    924:                daddr_t *bnp))) fdesc_badop)
                    925: #define        fdesc_strategy ((int (*) __P(( \
                    926:                struct buf *bp))) fdesc_badop)
                    927: #define fdesc_islocked ((int (*) __P(( \
                    928:                struct vnode *vp))) nullop)
                    929: #define fdesc_advlock ((int (*) __P(( \
                    930:                struct vnode *vp, \
                    931:                caddr_t id, \
                    932:                int op, \
                    933:                struct flock *fl, \
                    934:                int flags))) fdesc_enotsupp)
                    935:
                    936: struct vnodeops fdesc_vnodeops = {
                    937:        fdesc_lookup,   /* lookup */
                    938:        fdesc_create,   /* create */
                    939:        fdesc_mknod,    /* mknod */
                    940:        fdesc_open,     /* open */
                    941:        fdesc_close,    /* close */
                    942:        fdesc_access,   /* access */
                    943:        fdesc_getattr,  /* getattr */
                    944:        fdesc_setattr,  /* setattr */
                    945:        fdesc_read,     /* read */
                    946:        fdesc_write,    /* write */
                    947:        fdesc_ioctl,    /* ioctl */
                    948:        fdesc_select,   /* select */
                    949:        fdesc_mmap,     /* mmap */
                    950:        fdesc_fsync,    /* fsync */
                    951:        fdesc_seek,     /* seek */
                    952:        fdesc_remove,   /* remove */
                    953:        fdesc_link,     /* link */
                    954:        fdesc_rename,   /* rename */
                    955:        fdesc_mkdir,    /* mkdir */
                    956:        fdesc_rmdir,    /* rmdir */
                    957:        fdesc_symlink,  /* symlink */
                    958:        fdesc_readdir,  /* readdir */
                    959:        fdesc_readlink, /* readlink */
                    960:        fdesc_abortop,  /* abortop */
                    961:        fdesc_inactive, /* inactive */
                    962:        fdesc_reclaim,  /* reclaim */
                    963:        fdesc_lock,     /* lock */
                    964:        fdesc_unlock,   /* unlock */
                    965:        fdesc_bmap,     /* bmap */
                    966:        fdesc_strategy, /* strategy */
                    967:        fdesc_print,    /* print */
                    968:        fdesc_islocked, /* islocked */
                    969:        fdesc_advlock,  /* advlock */
                    970: };

CVSweb <webmaster@jp.NetBSD.org>