[BACK]Return to cd9660_vnops.c CVS log [TXT][DIR] Up to [local] / sys / isofs / cd9660

Annotation of sys/isofs/cd9660/cd9660_vnops.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: cd9660_vnops.c,v 1.43 2007/06/06 17:15:13 deraadt Exp $       */
        !             2: /*     $NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos Exp $       */
        !             3:
        !             4: /*-
        !             5:  * Copyright (c) 1994
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  *
        !             8:  * This code is derived from software contributed to Berkeley
        !             9:  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
        !            10:  * Support code is derived from software contributed to Berkeley
        !            11:  * by Atsushi Murai (amurai@spec.co.jp).
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. 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.
        !            24:  *
        !            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.
        !            36:  *
        !            37:  *     @(#)cd9660_vnops.c      8.15 (Berkeley) 12/5/94
        !            38:  */
        !            39:
        !            40: #include <sys/param.h>
        !            41: #include <sys/systm.h>
        !            42: #include <sys/namei.h>
        !            43: #include <sys/resourcevar.h>
        !            44: #include <sys/kernel.h>
        !            45: #include <sys/file.h>
        !            46: #include <sys/stat.h>
        !            47: #include <sys/buf.h>
        !            48: #include <sys/proc.h>
        !            49: #include <sys/conf.h>
        !            50: #include <sys/mount.h>
        !            51: #include <sys/vnode.h>
        !            52: #include <sys/malloc.h>
        !            53: #include <sys/pool.h>
        !            54: #include <sys/dirent.h>
        !            55: #include <sys/ioctl.h>
        !            56: #include <sys/ioccom.h>
        !            57: #include <sys/cdio.h>
        !            58: #include <sys/poll.h>
        !            59:
        !            60: #include <miscfs/fifofs/fifo.h>
        !            61: #include <miscfs/specfs/specdev.h>
        !            62:
        !            63: #include <isofs/cd9660/iso.h>
        !            64: #include <isofs/cd9660/cd9660_extern.h>
        !            65: #include <isofs/cd9660/cd9660_node.h>
        !            66: #include <isofs/cd9660/iso_rrip.h>
        !            67:
        !            68: /*
        !            69:  * Structure for reading directories
        !            70:  */
        !            71: struct isoreaddir {
        !            72:        struct dirent saveent;
        !            73:        struct dirent assocent;
        !            74:        struct dirent current;
        !            75:        off_t saveoff;
        !            76:        off_t assocoff;
        !            77:        off_t curroff;
        !            78:        struct uio *uio;
        !            79:        off_t uio_off;
        !            80:        int eofflag;
        !            81:        u_long *cookies;
        !            82:        int ncookies;
        !            83: };
        !            84:
        !            85: int    iso_uiodir(struct isoreaddir *, struct dirent *, off_t);
        !            86: int    iso_shipdir(struct isoreaddir *);
        !            87:
        !            88: #if 0
        !            89: /*
        !            90:  * Mknod vnode call
        !            91:  *  Actually remap the device number
        !            92:  */
        !            93: int
        !            94: cd9660_mknod(ndp, vap, cred, p)
        !            95:        struct nameidata *ndp;
        !            96:        struct ucred *cred;
        !            97:        struct vattr *vap;
        !            98:        struct proc *p;
        !            99: {
        !           100: #ifndef        ISODEVMAP
        !           101:        pool_put(&namei_pool, ndp->ni_pnbuf);
        !           102:        vput(ndp->ni_dvp);
        !           103:        vput(ndp->ni_vp);
        !           104:        return (EINVAL);
        !           105: #else
        !           106:        register struct vnode *vp;
        !           107:        struct iso_node *ip;
        !           108:        struct iso_dnode *dp;
        !           109:        int error;
        !           110:
        !           111:        vp = ndp->ni_vp;
        !           112:        ip = VTOI(vp);
        !           113:
        !           114:        if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
        !           115:            || vap->va_type != vp->v_type
        !           116:            || (vap->va_type != VCHR && vap->va_type != VBLK)) {
        !           117:                pool_put(&namei_pool, ndp->ni_pnbuf);
        !           118:                vput(ndp->ni_dvp);
        !           119:                vput(ndp->ni_vp);
        !           120:                return (EINVAL);
        !           121:        }
        !           122:
        !           123:        dp = iso_dmap(ip->i_dev,ip->i_number,1);
        !           124:        if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) {
        !           125:                /* same as the unmapped one, delete the mapping */
        !           126:                remque(dp);
        !           127:                FREE(dp, M_CACHE);
        !           128:        } else
        !           129:                /* enter new mapping */
        !           130:                dp->d_dev = vap->va_rdev;
        !           131:
        !           132:        /*
        !           133:         * Remove inode so that it will be reloaded by iget and
        !           134:         * checked to see if it is an alias of an existing entry
        !           135:         * in the inode cache.
        !           136:         */
        !           137:        vput(vp);
        !           138:        vp->v_type = VNON;
        !           139:        vgone(vp);
        !           140:        return (0);
        !           141: #endif
        !           142: }
        !           143: #endif
        !           144:
        !           145: /*
        !           146:  * Setattr call. Only allowed for block and character special devices.
        !           147:  */
        !           148: int
        !           149: cd9660_setattr(v)
        !           150:        void *v;
        !           151: {
        !           152:        struct vop_setattr_args *ap = v;
        !           153:        struct vnode *vp = ap->a_vp;
        !           154:        struct vattr *vap = ap->a_vap;
        !           155:
        !           156:        if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
        !           157:            vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
        !           158:            vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)
        !           159:                return (EROFS);
        !           160:        if (vap->va_size != VNOVAL) {
        !           161:                switch (vp->v_type) {
        !           162:                case VDIR:
        !           163:                        return (EISDIR);
        !           164:                case VLNK:
        !           165:                case VREG:
        !           166:                        return (EROFS);
        !           167:                case VCHR:
        !           168:                case VBLK:
        !           169:                case VSOCK:
        !           170:                case VFIFO:
        !           171:                        return (0);
        !           172:                default:
        !           173:                        return (EINVAL);
        !           174:                }
        !           175:        }
        !           176:
        !           177:        return (EINVAL);
        !           178: }
        !           179:
        !           180: /*
        !           181:  * Open called.
        !           182:  *
        !           183:  * Nothing to do.
        !           184:  */
        !           185: /* ARGSUSED */
        !           186: int
        !           187: cd9660_open(v)
        !           188:        void *v;
        !           189: {
        !           190:        return (0);
        !           191: }
        !           192:
        !           193: /*
        !           194:  * Close called
        !           195:  *
        !           196:  * Update the times on the inode on writeable file systems.
        !           197:  */
        !           198: /* ARGSUSED */
        !           199: int
        !           200: cd9660_close(v)
        !           201:        void *v;
        !           202: {
        !           203:        return (0);
        !           204: }
        !           205:
        !           206: /*
        !           207:  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
        !           208:  * The mode is shifted to select the owner/group/other fields. The
        !           209:  * super user is granted all permissions.
        !           210:  */
        !           211: int
        !           212: cd9660_access(v)
        !           213:        void *v;
        !           214: {
        !           215:        struct vop_access_args *ap = v;
        !           216:        struct iso_node *ip = VTOI(ap->a_vp);
        !           217:
        !           218:        return (vaccess(ip->inode.iso_mode & ALLPERMS, ip->inode.iso_uid,
        !           219:            ip->inode.iso_gid, ap->a_mode, ap->a_cred));
        !           220: }
        !           221:
        !           222: int
        !           223: cd9660_getattr(v)
        !           224:        void *v;
        !           225: {
        !           226:        struct vop_getattr_args *ap = v;
        !           227:        struct vnode *vp = ap->a_vp;
        !           228:        register struct vattr *vap = ap->a_vap;
        !           229:        register struct iso_node *ip = VTOI(vp);
        !           230:
        !           231:        vap->va_fsid    = ip->i_dev;
        !           232:        vap->va_fileid  = ip->i_number;
        !           233:
        !           234:        vap->va_mode    = ip->inode.iso_mode & ALLPERMS;
        !           235:        vap->va_nlink   = ip->inode.iso_links;
        !           236:        vap->va_uid     = ip->inode.iso_uid;
        !           237:        vap->va_gid     = ip->inode.iso_gid;
        !           238:        vap->va_atime   = ip->inode.iso_atime;
        !           239:        vap->va_mtime   = ip->inode.iso_mtime;
        !           240:        vap->va_ctime   = ip->inode.iso_ctime;
        !           241:        vap->va_rdev    = ip->inode.iso_rdev;
        !           242:
        !           243:        vap->va_size    = (u_quad_t) ip->i_size;
        !           244:        if (ip->i_size == 0 && vp->v_type  == VLNK) {
        !           245:                struct vop_readlink_args rdlnk;
        !           246:                struct iovec aiov;
        !           247:                struct uio auio;
        !           248:                char *cp;
        !           249:
        !           250:                MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
        !           251:                aiov.iov_base = cp;
        !           252:                aiov.iov_len = MAXPATHLEN;
        !           253:                auio.uio_iov = &aiov;
        !           254:                auio.uio_iovcnt = 1;
        !           255:                auio.uio_offset = 0;
        !           256:                auio.uio_rw = UIO_READ;
        !           257:                auio.uio_segflg = UIO_SYSSPACE;
        !           258:                auio.uio_procp = ap->a_p;
        !           259:                auio.uio_resid = MAXPATHLEN;
        !           260:                rdlnk.a_uio = &auio;
        !           261:                rdlnk.a_vp = ap->a_vp;
        !           262:                rdlnk.a_cred = ap->a_cred;
        !           263:                if (cd9660_readlink(&rdlnk) == 0)
        !           264:                        vap->va_size = MAXPATHLEN - auio.uio_resid;
        !           265:                FREE(cp, M_TEMP);
        !           266:        }
        !           267:        vap->va_flags   = 0;
        !           268:        vap->va_gen = 1;
        !           269:        vap->va_blocksize = ip->i_mnt->logical_block_size;
        !           270:        vap->va_bytes   = (u_quad_t) ip->i_size;
        !           271:        vap->va_type    = vp->v_type;
        !           272:        return (0);
        !           273: }
        !           274:
        !           275: /*
        !           276:  * Vnode op for reading.
        !           277:  */
        !           278: int
        !           279: cd9660_read(v)
        !           280:        void *v;
        !           281: {
        !           282:        struct vop_read_args *ap = v;
        !           283:        struct vnode *vp = ap->a_vp;
        !           284:        register struct uio *uio = ap->a_uio;
        !           285:        register struct iso_node *ip = VTOI(vp);
        !           286:        register struct iso_mnt *imp;
        !           287:        struct buf *bp;
        !           288:        daddr64_t lbn, rablock;
        !           289:        off_t diff;
        !           290:        int error = 0;
        !           291:        long size, n, on;
        !           292:
        !           293:        if (uio->uio_resid == 0)
        !           294:                return (0);
        !           295:        if (uio->uio_offset < 0)
        !           296:                return (EINVAL);
        !           297:        ip->i_flag |= IN_ACCESS;
        !           298:        imp = ip->i_mnt;
        !           299:        do {
        !           300:                struct cluster_info *ci = &ip->i_ci;
        !           301:
        !           302:                lbn = lblkno(imp, uio->uio_offset);
        !           303:                on = blkoff(imp, uio->uio_offset);
        !           304:                n = min((u_int)(imp->logical_block_size - on),
        !           305:                        uio->uio_resid);
        !           306:                diff = (off_t)ip->i_size - uio->uio_offset;
        !           307:                if (diff <= 0)
        !           308:                        return (0);
        !           309:                if (diff < n)
        !           310:                        n = diff;
        !           311:                size = blksize(imp, ip, lbn);
        !           312:                rablock = lbn + 1;
        !           313: #define MAX_RA 32
        !           314:                if (ci->ci_lastr + 1 == lbn) {
        !           315:                        struct ra {
        !           316:                                daddr64_t blks[MAX_RA];
        !           317:                                int sizes[MAX_RA];
        !           318:                        } *ra;
        !           319:                        int i;
        !           320:
        !           321:                        MALLOC(ra, struct ra *, sizeof *ra,
        !           322:                            M_TEMP, M_WAITOK);
        !           323:                        for (i = 0; i < MAX_RA &&
        !           324:                            lblktosize(imp, (rablock + i)) < ip->i_size;
        !           325:                            i++) {
        !           326:                                ra->blks[i] = rablock + i;
        !           327:                                ra->sizes[i] = blksize(imp, ip, rablock + i);
        !           328:                        }
        !           329:                        error = breadn(vp, lbn, size, ra->blks,
        !           330:                            ra->sizes, i, NOCRED, &bp);
        !           331:                        FREE(ra, M_TEMP);
        !           332:                } else
        !           333:                        error = bread(vp, lbn, size, NOCRED, &bp);
        !           334:                ci->ci_lastr = lbn;
        !           335:                n = min(n, size - bp->b_resid);
        !           336:                if (error) {
        !           337:                        brelse(bp);
        !           338:                        return (error);
        !           339:                }
        !           340:
        !           341:                error = uiomove(bp->b_data + on, (int)n, uio);
        !           342:
        !           343:                 if (n + on == imp->logical_block_size ||
        !           344:                    uio->uio_offset == (off_t)ip->i_size)
        !           345:                        bp->b_flags |= B_AGE;
        !           346:                brelse(bp);
        !           347:        } while (error == 0 && uio->uio_resid > 0 && n != 0);
        !           348:        return (error);
        !           349: }
        !           350:
        !           351: /* ARGSUSED */
        !           352: int
        !           353: cd9660_ioctl(v)
        !           354:        void *v;
        !           355: {
        !           356:        return (ENOTTY);
        !           357: }
        !           358:
        !           359: /* ARGSUSED */
        !           360: int
        !           361: cd9660_poll(v)
        !           362:        void *v;
        !           363: {
        !           364:        struct vop_poll_args *ap = v;
        !           365:
        !           366:        /*
        !           367:         * We should really check to see if I/O is possible.
        !           368:         */
        !           369:        return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM));
        !           370: }
        !           371:
        !           372: /*
        !           373:  * Mmap a file
        !           374:  *
        !           375:  * NB Currently unsupported.
        !           376:  */
        !           377: /* ARGSUSED */
        !           378: int
        !           379: cd9660_mmap(v)
        !           380:        void *v;
        !           381: {
        !           382:
        !           383:        return (EINVAL);
        !           384: }
        !           385:
        !           386: /*
        !           387:  * Seek on a file
        !           388:  *
        !           389:  * Nothing to do, so just return.
        !           390:  */
        !           391: /* ARGSUSED */
        !           392: int
        !           393: cd9660_seek(v)
        !           394:        void *v;
        !           395: {
        !           396:        return (0);
        !           397: }
        !           398:
        !           399: int
        !           400: iso_uiodir(idp,dp,off)
        !           401:        struct isoreaddir *idp;
        !           402:        struct dirent *dp;
        !           403:        off_t off;
        !           404: {
        !           405:        int error;
        !           406:
        !           407:        dp->d_name[dp->d_namlen] = 0;
        !           408:        dp->d_reclen = DIRENT_SIZE(dp);
        !           409:
        !           410:        if (idp->uio->uio_resid < dp->d_reclen) {
        !           411:                idp->eofflag = 0;
        !           412:                return (-1);
        !           413:        }
        !           414:
        !           415:        if (idp->cookies) {
        !           416:                if (idp->ncookies <= 0) {
        !           417:                        idp->eofflag = 0;
        !           418:                        return (-1);
        !           419:                }
        !           420:
        !           421:                *idp->cookies++ = off;
        !           422:                --idp->ncookies;
        !           423:        }
        !           424:
        !           425:        if ((error = uiomove((caddr_t)dp, dp->d_reclen, idp->uio)) != 0)
        !           426:                return (error);
        !           427:        idp->uio_off = off;
        !           428:        return (0);
        !           429: }
        !           430:
        !           431: int
        !           432: iso_shipdir(idp)
        !           433:        struct isoreaddir *idp;
        !           434: {
        !           435:        struct dirent *dp;
        !           436:        int cl, sl, assoc;
        !           437:        int error;
        !           438:        char *cname, *sname;
        !           439:
        !           440:        cl = idp->current.d_namlen;
        !           441:        cname = idp->current.d_name;
        !           442:
        !           443:        if ((assoc = cl > 1 && *cname == ASSOCCHAR)) {
        !           444:                cl--;
        !           445:                cname++;
        !           446:        }
        !           447:
        !           448:        dp = &idp->saveent;
        !           449:        sname = dp->d_name;
        !           450:        if (!(sl = dp->d_namlen)) {
        !           451:                dp = &idp->assocent;
        !           452:                sname = dp->d_name + 1;
        !           453:                sl = dp->d_namlen - 1;
        !           454:        }
        !           455:        if (sl > 0) {
        !           456:                if (sl != cl
        !           457:                    || bcmp(sname,cname,sl)) {
        !           458:                        if (idp->assocent.d_namlen) {
        !           459:                                error = iso_uiodir(idp, &idp->assocent,
        !           460:                                                   idp->assocoff);
        !           461:                                if (error)
        !           462:                                        return (error);
        !           463:                                idp->assocent.d_namlen = 0;
        !           464:                        }
        !           465:                        if (idp->saveent.d_namlen) {
        !           466:                                error = iso_uiodir(idp, &idp->saveent,
        !           467:                                                   idp->saveoff);
        !           468:                                if (error)
        !           469:                                        return (error);
        !           470:                                idp->saveent.d_namlen = 0;
        !           471:                        }
        !           472:                }
        !           473:        }
        !           474:        idp->current.d_reclen = DIRENT_SIZE(&idp->current);
        !           475:        if (assoc) {
        !           476:                idp->assocoff = idp->curroff;
        !           477:                bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
        !           478:        } else {
        !           479:                idp->saveoff = idp->curroff;
        !           480:                bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
        !           481:        }
        !           482:        return (0);
        !           483: }
        !           484:
        !           485: /*
        !           486:  * Vnode op for readdir
        !           487:  */
        !           488: int
        !           489: cd9660_readdir(v)
        !           490:        void *v;
        !           491: {
        !           492:        struct vop_readdir_args *ap = v;
        !           493:        register struct uio *uio = ap->a_uio;
        !           494:        struct isoreaddir *idp;
        !           495:        struct vnode *vdp = ap->a_vp;
        !           496:        struct iso_node *dp;
        !           497:        struct iso_mnt *imp;
        !           498:        struct buf *bp = NULL;
        !           499:        struct iso_directory_record *ep;
        !           500:        int entryoffsetinblock;
        !           501:        doff_t endsearch;
        !           502:        u_long bmask;
        !           503:        int error = 0;
        !           504:        int reclen;
        !           505:        u_short namelen;
        !           506:        int  ncookies = 0;
        !           507:        u_long *cookies = NULL;
        !           508:
        !           509:        dp = VTOI(vdp);
        !           510:        imp = dp->i_mnt;
        !           511:        bmask = imp->im_bmask;
        !           512:
        !           513:        MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
        !           514:        idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
        !           515:        /*
        !           516:         * XXX
        !           517:         * Is it worth trying to figure out the type?
        !           518:         */
        !           519:        idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
        !           520:            DT_UNKNOWN;
        !           521:        idp->uio = uio;
        !           522:        if (ap->a_ncookies == NULL) {
        !           523:                idp->cookies = NULL;
        !           524:        } else {
        !           525:                /*
        !           526:                 * Guess the number of cookies needed.
        !           527:                 */
        !           528:                ncookies = uio->uio_resid / 16;
        !           529:                MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP,
        !           530:                    M_WAITOK);
        !           531:                idp->cookies = cookies;
        !           532:                idp->ncookies = ncookies;
        !           533:        }
        !           534:        idp->eofflag = 1;
        !           535:        idp->curroff = uio->uio_offset;
        !           536:
        !           537:        if ((entryoffsetinblock = idp->curroff & bmask) &&
        !           538:            (error = cd9660_bufatoff(dp, (off_t)idp->curroff, NULL, &bp))) {
        !           539:                FREE(idp, M_TEMP);
        !           540:                return (error);
        !           541:        }
        !           542:        endsearch = dp->i_size;
        !           543:
        !           544:        while (idp->curroff < endsearch) {
        !           545:                /*
        !           546:                 * If offset is on a block boundary,
        !           547:                 * read the next directory block.
        !           548:                 * Release previous if it exists.
        !           549:                 */
        !           550:                if ((idp->curroff & bmask) == 0) {
        !           551:                        if (bp != NULL)
        !           552:                                brelse(bp);
        !           553:                        error = cd9660_bufatoff(dp, (off_t)idp->curroff,
        !           554:                                             NULL, &bp);
        !           555:                        if (error)
        !           556:                                break;
        !           557:                        entryoffsetinblock = 0;
        !           558:                }
        !           559:                /*
        !           560:                 * Get pointer to next entry.
        !           561:                 */
        !           562:                ep = (struct iso_directory_record *)
        !           563:                        ((char *)bp->b_data + entryoffsetinblock);
        !           564:
        !           565:                reclen = isonum_711(ep->length);
        !           566:                if (reclen == 0) {
        !           567:                        /* skip to next block, if any */
        !           568:                        idp->curroff =
        !           569:                            (idp->curroff & ~bmask) + imp->logical_block_size;
        !           570:                        continue;
        !           571:                }
        !           572:
        !           573:                if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
        !           574:                        error = EINVAL;
        !           575:                        /* illegal entry, stop */
        !           576:                        break;
        !           577:                }
        !           578:
        !           579:                if (entryoffsetinblock + reclen > imp->logical_block_size) {
        !           580:                        error = EINVAL;
        !           581:                        /* illegal directory, so stop looking */
        !           582:                        break;
        !           583:                }
        !           584:
        !           585:                idp->current.d_namlen = isonum_711(ep->name_len);
        !           586:
        !           587:                if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
        !           588:                        error = EINVAL;
        !           589:                        /* illegal entry, stop */
        !           590:                        break;
        !           591:                }
        !           592:
        !           593:                if (isonum_711(ep->flags)&2)
        !           594:                        idp->current.d_fileno = isodirino(ep, imp);
        !           595:                else
        !           596:                        idp->current.d_fileno = dbtob(bp->b_blkno) +
        !           597:                                entryoffsetinblock;
        !           598:
        !           599:                idp->curroff += reclen;
        !           600:
        !           601:                switch (imp->iso_ftype) {
        !           602:                case ISO_FTYPE_RRIP:
        !           603:                        cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
        !           604:                                           &idp->current.d_fileno,imp);
        !           605:                        idp->current.d_namlen = (u_char)namelen;
        !           606:                        if (idp->current.d_namlen)
        !           607:                                error = iso_uiodir(idp,&idp->current,idp->curroff);
        !           608:                        break;
        !           609:                default:        /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
        !           610:                        strlcpy(idp->current.d_name,"..",
        !           611:                            sizeof idp->current.d_name);
        !           612:                        if (idp->current.d_namlen == 1 && ep->name[0] == 0) {
        !           613:                                idp->current.d_namlen = 1;
        !           614:                                error = iso_uiodir(idp,&idp->current,idp->curroff);
        !           615:                        } else if (idp->current.d_namlen == 1 &&
        !           616:                            ep->name[0] == 1) {
        !           617:                                idp->current.d_namlen = 2;
        !           618:                                error = iso_uiodir(idp,&idp->current,idp->curroff);
        !           619:                        } else {
        !           620:                                isofntrans(ep->name,idp->current.d_namlen,
        !           621:                                           idp->current.d_name, &namelen,
        !           622:                                           imp->iso_ftype == ISO_FTYPE_9660,
        !           623:                                           isonum_711(ep->flags) & 4,
        !           624:                                           imp->joliet_level);
        !           625:                                idp->current.d_namlen = (u_char)namelen;
        !           626:                                if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
        !           627:                                        error = iso_shipdir(idp);
        !           628:                                else
        !           629:                                        error = iso_uiodir(idp,&idp->current,idp->curroff);
        !           630:                        }
        !           631:                }
        !           632:                if (error)
        !           633:                        break;
        !           634:
        !           635:                entryoffsetinblock += reclen;
        !           636:        }
        !           637:
        !           638:        if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
        !           639:                idp->current.d_namlen = 0;
        !           640:                error = iso_shipdir(idp);
        !           641:        }
        !           642:        if (error < 0)
        !           643:                error = 0;
        !           644:
        !           645:        if (ap->a_ncookies != NULL) {
        !           646:                if (error)
        !           647:                        free(cookies, M_TEMP);
        !           648:                else {
        !           649:                        /*
        !           650:                         * Work out the number of cookies actually used.
        !           651:                         */
        !           652:                        *ap->a_ncookies = ncookies - idp->ncookies;
        !           653:                        *ap->a_cookies = cookies;
        !           654:                }
        !           655:        }
        !           656:
        !           657:        if (bp)
        !           658:                brelse (bp);
        !           659:
        !           660:        uio->uio_offset = idp->uio_off;
        !           661:        *ap->a_eofflag = idp->eofflag;
        !           662:
        !           663:        FREE(idp, M_TEMP);
        !           664:
        !           665:        return (error);
        !           666: }
        !           667:
        !           668: /*
        !           669:  * Return target name of a symbolic link
        !           670:  * Shouldn't we get the parent vnode and read the data from there?
        !           671:  * This could eventually result in deadlocks in cd9660_lookup.
        !           672:  * But otherwise the block read here is in the block buffer two times.
        !           673:  */
        !           674: typedef struct iso_directory_record ISODIR;
        !           675: typedef struct iso_node             ISONODE;
        !           676: typedef struct iso_mnt              ISOMNT;
        !           677: int
        !           678: cd9660_readlink(v)
        !           679:        void *v;
        !           680: {
        !           681:        struct vop_readlink_args *ap = v;
        !           682:        ISONODE *ip;
        !           683:        ISODIR  *dirp;
        !           684:        ISOMNT  *imp;
        !           685:        struct  buf *bp;
        !           686:        struct  uio *uio;
        !           687:        u_short symlen;
        !           688:        int     error;
        !           689:        char    *symname;
        !           690:
        !           691:        ip  = VTOI(ap->a_vp);
        !           692:        imp = ip->i_mnt;
        !           693:        uio = ap->a_uio;
        !           694:
        !           695:        if (imp->iso_ftype != ISO_FTYPE_RRIP)
        !           696:                return (EINVAL);
        !           697:
        !           698:        /*
        !           699:         * Get parents directory record block that this inode included.
        !           700:         */
        !           701:        error = bread(imp->im_devvp,
        !           702:                      (ip->i_number >> imp->im_bshift) <<
        !           703:                      (imp->im_bshift - DEV_BSHIFT),
        !           704:                      imp->logical_block_size, NOCRED, &bp);
        !           705:        if (error) {
        !           706:                brelse(bp);
        !           707:                return (EINVAL);
        !           708:        }
        !           709:
        !           710:        /*
        !           711:         * Setup the directory pointer for this inode
        !           712:         */
        !           713:        dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
        !           714:
        !           715:        /*
        !           716:         * Just make sure, we have a right one....
        !           717:         *   1: Check not cross boundary on block
        !           718:         */
        !           719:        if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
        !           720:            > imp->logical_block_size) {
        !           721:                brelse(bp);
        !           722:                return (EINVAL);
        !           723:        }
        !           724:
        !           725:        /*
        !           726:         * Now get a buffer
        !           727:         * Abuse a namei buffer for now.
        !           728:         */
        !           729:        if (uio->uio_segflg == UIO_SYSSPACE &&
        !           730:            uio->uio_iov->iov_len >= MAXPATHLEN)
        !           731:                symname = uio->uio_iov->iov_base;
        !           732:        else
        !           733:                symname = pool_get(&namei_pool, PR_WAITOK);
        !           734:
        !           735:        /*
        !           736:         * Ok, we just gathering a symbolic name in SL record.
        !           737:         */
        !           738:        if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
        !           739:                if (uio->uio_segflg != UIO_SYSSPACE ||
        !           740:                    uio->uio_iov->iov_len < MAXPATHLEN)
        !           741:                        pool_put(&namei_pool, symname);
        !           742:                brelse(bp);
        !           743:                return (EINVAL);
        !           744:        }
        !           745:        /*
        !           746:         * Don't forget before you leave from home ;-)
        !           747:         */
        !           748:        brelse(bp);
        !           749:
        !           750:        /*
        !           751:         * return with the symbolic name to caller's.
        !           752:         */
        !           753:        if (uio->uio_segflg != UIO_SYSSPACE ||
        !           754:            uio->uio_iov->iov_len < MAXPATHLEN) {
        !           755:                error = uiomove(symname, symlen, uio);
        !           756:                pool_put(&namei_pool, symname);
        !           757:                return (error);
        !           758:        }
        !           759:        uio->uio_resid -= symlen;
        !           760:        (char *)uio->uio_iov->iov_base += symlen;
        !           761:        uio->uio_iov->iov_len -= symlen;
        !           762:        return (0);
        !           763: }
        !           764:
        !           765: int
        !           766: cd9660_link(v)
        !           767:        void *v;
        !           768: {
        !           769:        struct vop_link_args *ap = v;
        !           770:
        !           771:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
        !           772:        vput(ap->a_dvp);
        !           773:        return (EROFS);
        !           774: }
        !           775:
        !           776: int
        !           777: cd9660_symlink(v)
        !           778:        void *v;
        !           779: {
        !           780:        struct vop_symlink_args *ap = v;
        !           781:
        !           782:        VOP_ABORTOP(ap->a_dvp, ap->a_cnp);
        !           783:        vput(ap->a_dvp);
        !           784:        return (EROFS);
        !           785: }
        !           786:
        !           787: /*
        !           788:  * Lock an inode.
        !           789:  */
        !           790: int
        !           791: cd9660_lock(v)
        !           792:        void *v;
        !           793: {
        !           794:        struct vop_lock_args *ap = v;
        !           795:        struct vnode *vp = ap->a_vp;
        !           796:
        !           797:        return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, NULL));
        !           798: }
        !           799:
        !           800: /*
        !           801:  * Unlock an inode.
        !           802:  */
        !           803: int
        !           804: cd9660_unlock(v)
        !           805:        void *v;
        !           806: {
        !           807:        struct vop_unlock_args *ap = v;
        !           808:        struct vnode *vp = ap->a_vp;
        !           809:
        !           810:        return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, NULL));
        !           811: }
        !           812:
        !           813: /*
        !           814:  * Calculate the logical to physical mapping if not done already,
        !           815:  * then call the device strategy routine.
        !           816:  */
        !           817: int
        !           818: cd9660_strategy(v)
        !           819:        void *v;
        !           820: {
        !           821:        struct vop_strategy_args *ap = v;
        !           822:        struct buf *bp = ap->a_bp;
        !           823:        struct vnode *vp = bp->b_vp;
        !           824:        struct iso_node *ip;
        !           825:        int error;
        !           826:        int s;
        !           827:
        !           828:        ip = VTOI(vp);
        !           829:        if (vp->v_type == VBLK || vp->v_type == VCHR)
        !           830:                panic("cd9660_strategy: spec");
        !           831:        if (bp->b_blkno == bp->b_lblkno) {
        !           832:                error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL);
        !           833:                if (error) {
        !           834:                        bp->b_error = error;
        !           835:                        bp->b_flags |= B_ERROR;
        !           836:                        s = splbio();
        !           837:                        biodone(bp);
        !           838:                        splx(s);
        !           839:                        return (error);
        !           840:                }
        !           841:                if ((long)bp->b_blkno == -1)
        !           842:                        clrbuf(bp);
        !           843:        }
        !           844:        if ((long)bp->b_blkno == -1) {
        !           845:                s = splbio();
        !           846:                biodone(bp);
        !           847:                splx(s);
        !           848:                return (0);
        !           849:        }
        !           850:        vp = ip->i_devvp;
        !           851:        bp->b_dev = vp->v_rdev;
        !           852:        VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
        !           853:        return (0);
        !           854: }
        !           855:
        !           856: /*
        !           857:  * Print out the contents of an inode.
        !           858:  */
        !           859: /*ARGSUSED*/
        !           860: int
        !           861: cd9660_print(v)
        !           862:        void *v;
        !           863: {
        !           864:        printf("tag VT_ISOFS, isofs vnode\n");
        !           865:        return (0);
        !           866: }
        !           867:
        !           868: /*
        !           869:  * Check for a locked inode.
        !           870:  */
        !           871: int
        !           872: cd9660_islocked(v)
        !           873:        void *v;
        !           874: {
        !           875:        struct vop_islocked_args *ap = v;
        !           876:
        !           877:        return (lockstatus(&VTOI(ap->a_vp)->i_lock));
        !           878: }
        !           879:
        !           880: /*
        !           881:  * Return POSIX pathconf information applicable to cd9660 filesystems.
        !           882:  */
        !           883: int
        !           884: cd9660_pathconf(v)
        !           885:        void *v;
        !           886: {
        !           887:        struct vop_pathconf_args *ap = v;
        !           888:        switch (ap->a_name) {
        !           889:        case _PC_LINK_MAX:
        !           890:                *ap->a_retval = 1;
        !           891:                return (0);
        !           892:        case _PC_NAME_MAX:
        !           893:                if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
        !           894:                        *ap->a_retval = NAME_MAX;
        !           895:                else
        !           896:                        *ap->a_retval = 37;
        !           897:                return (0);
        !           898:        case _PC_PATH_MAX:
        !           899:                *ap->a_retval = PATH_MAX;
        !           900:                return (0);
        !           901:        case _PC_PIPE_BUF:
        !           902:                *ap->a_retval = PIPE_BUF;
        !           903:                return (0);
        !           904:        case _PC_CHOWN_RESTRICTED:
        !           905:                *ap->a_retval = 1;
        !           906:                return (0);
        !           907:        case _PC_NO_TRUNC:
        !           908:                *ap->a_retval = 1;
        !           909:                return (0);
        !           910:        default:
        !           911:                return (EINVAL);
        !           912:        }
        !           913:        /* NOTREACHED */
        !           914: }
        !           915:
        !           916: /*
        !           917:  * Global vfs data structures for isofs
        !           918:  */
        !           919: #define        cd9660_create   eopnotsupp
        !           920: #define        cd9660_mknod    eopnotsupp
        !           921: #define        cd9660_write    eopnotsupp
        !           922: #define        cd9660_fsync    nullop
        !           923: #define        cd9660_remove   eopnotsupp
        !           924: #define        cd9660_rename   eopnotsupp
        !           925: #define        cd9660_mkdir    eopnotsupp
        !           926: #define        cd9660_rmdir    eopnotsupp
        !           927: #define        cd9660_advlock  eopnotsupp
        !           928: #define        cd9660_valloc   eopnotsupp
        !           929: #define        cd9660_vfree    eopnotsupp
        !           930: #define        cd9660_truncate eopnotsupp
        !           931: #define        cd9660_update   eopnotsupp
        !           932: #define        cd9660_bwrite   eopnotsupp
        !           933: #define cd9660_revoke   vop_generic_revoke
        !           934:
        !           935: /*
        !           936:  * Global vfs data structures for cd9660
        !           937:  */
        !           938: int (**cd9660_vnodeop_p)(void *);
        !           939: struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
        !           940:        { &vop_default_desc, vn_default_error },
        !           941:        { &vop_lookup_desc, cd9660_lookup },    /* lookup */
        !           942:        { &vop_create_desc, cd9660_create },    /* create */
        !           943:        { &vop_mknod_desc, cd9660_mknod },      /* mknod */
        !           944:        { &vop_open_desc, cd9660_open },        /* open */
        !           945:        { &vop_close_desc, cd9660_close },      /* close */
        !           946:        { &vop_access_desc, cd9660_access },    /* access */
        !           947:        { &vop_getattr_desc, cd9660_getattr },  /* getattr */
        !           948:        { &vop_setattr_desc, cd9660_setattr },  /* setattr */
        !           949:        { &vop_read_desc, cd9660_read },        /* read */
        !           950:        { &vop_write_desc, cd9660_write },      /* write */
        !           951:        { &vop_ioctl_desc, cd9660_ioctl },      /* ioctl */
        !           952:        { &vop_poll_desc, cd9660_poll },        /* poll */
        !           953:        { &vop_revoke_desc, cd9660_revoke },    /* revoke */
        !           954:        { &vop_fsync_desc, cd9660_fsync },      /* fsync */
        !           955:        { &vop_remove_desc, cd9660_remove },    /* remove */
        !           956:        { &vop_link_desc, cd9660_link },        /* link */
        !           957:        { &vop_rename_desc, cd9660_rename },    /* rename */
        !           958:        { &vop_mkdir_desc, cd9660_mkdir },      /* mkdir */
        !           959:        { &vop_rmdir_desc, cd9660_rmdir },      /* rmdir */
        !           960:        { &vop_symlink_desc, cd9660_symlink },  /* symlink */
        !           961:        { &vop_readdir_desc, cd9660_readdir },  /* readdir */
        !           962:        { &vop_readlink_desc, cd9660_readlink },/* readlink */
        !           963:        { &vop_abortop_desc, vop_generic_abortop },     /* abortop */
        !           964:        { &vop_inactive_desc, cd9660_inactive },/* inactive */
        !           965:        { &vop_reclaim_desc, cd9660_reclaim },  /* reclaim */
        !           966:        { &vop_lock_desc, cd9660_lock },        /* lock */
        !           967:        { &vop_unlock_desc, cd9660_unlock },    /* unlock */
        !           968:        { &vop_bmap_desc, cd9660_bmap },        /* bmap */
        !           969:        { &vop_strategy_desc, cd9660_strategy },/* strategy */
        !           970:        { &vop_print_desc, cd9660_print },      /* print */
        !           971:        { &vop_islocked_desc, cd9660_islocked },/* islocked */
        !           972:        { &vop_pathconf_desc, cd9660_pathconf },/* pathconf */
        !           973:        { &vop_advlock_desc, cd9660_advlock },  /* advlock */
        !           974:        { &vop_bwrite_desc, vop_generic_bwrite },
        !           975:        { NULL, NULL }
        !           976: };
        !           977: struct vnodeopv_desc cd9660_vnodeop_opv_desc =
        !           978:        { &cd9660_vnodeop_p, cd9660_vnodeop_entries };
        !           979:
        !           980: /*
        !           981:  * Special device vnode ops
        !           982:  */
        !           983: int (**cd9660_specop_p)(void *);
        !           984: struct vnodeopv_entry_desc cd9660_specop_entries[] = {
        !           985:        { &vop_default_desc, spec_vnoperate },
        !           986:        { &vop_access_desc, cd9660_access },    /* access */
        !           987:        { &vop_getattr_desc, cd9660_getattr },  /* getattr */
        !           988:        { &vop_setattr_desc, cd9660_setattr },  /* setattr */
        !           989:        { &vop_inactive_desc, cd9660_inactive },/* inactive */
        !           990:        { &vop_reclaim_desc, cd9660_reclaim },  /* reclaim */
        !           991:        { &vop_lock_desc, cd9660_lock },        /* lock */
        !           992:        { &vop_unlock_desc, cd9660_unlock },    /* unlock */
        !           993:        { &vop_print_desc, cd9660_print },      /* print */
        !           994:        { &vop_islocked_desc, cd9660_islocked },/* islocked */
        !           995:        { NULL, NULL }
        !           996: };
        !           997: struct vnodeopv_desc cd9660_specop_opv_desc =
        !           998:        { &cd9660_specop_p, cd9660_specop_entries };
        !           999:
        !          1000: #ifdef FIFO
        !          1001: int (**cd9660_fifoop_p)(void *);
        !          1002: struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
        !          1003:        { &vop_default_desc, fifo_vnoperate },
        !          1004:        { &vop_access_desc, cd9660_access },    /* access */
        !          1005:        { &vop_getattr_desc, cd9660_getattr },  /* getattr */
        !          1006:        { &vop_setattr_desc, cd9660_setattr },  /* setattr */
        !          1007:        { &vop_inactive_desc, cd9660_inactive },/* inactive */
        !          1008:        { &vop_reclaim_desc, cd9660_reclaim },  /* reclaim */
        !          1009:        { &vop_lock_desc, cd9660_lock },        /* lock */
        !          1010:        { &vop_unlock_desc, cd9660_unlock },    /* unlock */
        !          1011:        { &vop_print_desc, cd9660_print },      /* print */
        !          1012:        { &vop_islocked_desc, cd9660_islocked },/* islocked */
        !          1013:        { &vop_bwrite_desc, vop_generic_bwrite },
        !          1014:        { NULL, NULL }
        !          1015: };
        !          1016: struct vnodeopv_desc cd9660_fifoop_opv_desc =
        !          1017:        { &cd9660_fifoop_p, cd9660_fifoop_entries };
        !          1018: #endif /* FIFO */

CVSweb