Annotation of kernel/bsd/isofs/cd9660/cd9660_vnops.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*     $NetBSD: cd9660_vnops.c,v 1.22 1994/12/27 19:05:12 mycroft Exp $        */
        !            26: 
        !            27: /*-
        !            28:  * Copyright (c) 1994
        !            29:  *     The Regents of the University of California.  All rights reserved.
        !            30:  *
        !            31:  * This code is derived from software contributed to Berkeley
        !            32:  * by Pace Willisson ([email protected]).  The Rock Ridge Extension
        !            33:  * Support code is derived from software contributed to Berkeley
        !            34:  * by Atsushi Murai ([email protected]).
        !            35:  *
        !            36:  * Redistribution and use in source and binary forms, with or without
        !            37:  * modification, are permitted provided that the following conditions
        !            38:  * are met:
        !            39:  * 1. Redistributions of source code must retain the above copyright
        !            40:  *    notice, this list of conditions and the following disclaimer.
        !            41:  * 2. Redistributions in binary form must reproduce the above copyright
        !            42:  *    notice, this list of conditions and the following disclaimer in the
        !            43:  *    documentation and/or other materials provided with the distribution.
        !            44:  * 3. All advertising materials mentioning features or use of this software
        !            45:  *    must display the following acknowledgement:
        !            46:  *     This product includes software developed by the University of
        !            47:  *     California, Berkeley and its contributors.
        !            48:  * 4. Neither the name of the University nor the names of its contributors
        !            49:  *    may be used to endorse or promote products derived from this software
        !            50:  *    without specific prior written permission.
        !            51:  *
        !            52:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            53:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            54:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            55:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            56:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            57:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            58:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            59:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            60:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            61:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            62:  * SUCH DAMAGE.
        !            63:  *
        !            64:  *     @(#)cd9660_vnops.c      8.15 (Berkeley) 12/5/94
        !            65:  */
        !            66: 
        !            67: #include <sys/param.h>
        !            68: #include <sys/systm.h>
        !            69: #include <sys/namei.h>
        !            70: #include <sys/resourcevar.h>
        !            71: #include <sys/kernel.h>
        !            72: #include <sys/file.h>
        !            73: #include <sys/stat.h>
        !            74: #include <sys/buf.h>
        !            75: #include <sys/proc.h>
        !            76: #include <sys/conf.h>
        !            77: #include <sys/mount.h>
        !            78: #include <sys/vnode.h>
        !            79: #include <miscfs/specfs/specdev.h>
        !            80: #include <miscfs/fifofs/fifo.h>
        !            81: #include <sys/malloc.h>
        !            82: #include <sys/dir.h>
        !            83: #include <sys/attr.h>
        !            84: #include <vfs/vfs_support.h>
        !            85: 
        !            86: #include <sys/lock.h>
        !            87: 
        !            88: #include <isofs/cd9660/iso.h>
        !            89: #include <isofs/cd9660/cd9660_node.h>
        !            90: #include <isofs/cd9660/iso_rrip.h>
        !            91: 
        !            92: 
        !            93: #if 0
        !            94: /*
        !            95:  * Mknod vnode call
        !            96:  *  Actually remap the device number
        !            97:  */
        !            98: cd9660_mknod(ndp, vap, cred, p)
        !            99:        struct nameidata *ndp;
        !           100:        struct ucred *cred;
        !           101:        struct vattr *vap;
        !           102:        struct proc *p;
        !           103: {
        !           104: #ifndef        ISODEVMAP
        !           105:        FREE_ZONE(ndp->ni_pnbuf, ndp->ni_pnlen, M_NAMEI);
        !           106:        vput(ndp->ni_dvp);
        !           107:        vput(ndp->ni_vp);
        !           108:        return (EINVAL);
        !           109: #else
        !           110:        register struct vnode *vp;
        !           111:        struct iso_node *ip;
        !           112:        struct iso_dnode *dp;
        !           113:        int error;
        !           114: 
        !           115:        vp = ndp->ni_vp;
        !           116:        ip = VTOI(vp);
        !           117: 
        !           118:        if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP
        !           119:            || vap->va_type != vp->v_type
        !           120:            || (vap->va_type != VCHR && vap->va_type != VBLK)) {
        !           121:                FREE_ZONE(ndp->ni_pnbuf, ndp->ni_pnlen, M_NAMEI);
        !           122:                vput(ndp->ni_dvp);
        !           123:                vput(ndp->ni_vp);
        !           124:                return (EINVAL);
        !           125:        }
        !           126: 
        !           127:        dp = iso_dmap(ip->i_dev,ip->i_number,1);
        !           128:        if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) {
        !           129:                /* same as the unmapped one, delete the mapping */
        !           130:                remque(dp);
        !           131:                FREE(dp,M_CACHE);
        !           132:        } else
        !           133:                /* enter new mapping */
        !           134:                dp->d_dev = vap->va_rdev;
        !           135: 
        !           136:        /*
        !           137:         * Remove inode so that it will be reloaded by iget and
        !           138:         * checked to see if it is an alias of an existing entry
        !           139:         * in the inode cache.
        !           140:         */
        !           141:        vput(vp);
        !           142:        vp->v_type = VNON;
        !           143:        vgone(vp);
        !           144:        return (0);
        !           145: #endif
        !           146: }
        !           147: #endif
        !           148: 
        !           149: /*
        !           150:  * Open called.
        !           151:  *
        !           152:  * Nothing to do.
        !           153:  */
        !           154: /* ARGSUSED */
        !           155: int
        !           156: cd9660_open(ap)
        !           157:        struct vop_open_args /* {
        !           158:                struct vnode *a_vp;
        !           159:                int  a_mode;
        !           160:                struct ucred *a_cred;
        !           161:                struct proc *a_p;
        !           162:        } */ *ap;
        !           163: {
        !           164:        return (0);
        !           165: }
        !           166: 
        !           167: /*
        !           168:  * Close called
        !           169:  *
        !           170:  * Update the times on the inode on writeable file systems.
        !           171:  */
        !           172: /* ARGSUSED */
        !           173: int
        !           174: cd9660_close(ap)
        !           175:        struct vop_close_args /* {
        !           176:                struct vnode *a_vp;
        !           177:                int  a_fflag;
        !           178:                struct ucred *a_cred;
        !           179:                struct proc *a_p;
        !           180:        } */ *ap;
        !           181: {
        !           182:        return (0);
        !           183: }
        !           184: 
        !           185: /*
        !           186:  * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC.
        !           187:  * The mode is shifted to select the owner/group/other fields. The
        !           188:  * super user is granted all permissions.
        !           189:  */
        !           190: /* ARGSUSED */
        !           191: int
        !           192: cd9660_access(ap)
        !           193:        struct vop_access_args /* {
        !           194:                struct vnode *a_vp;
        !           195:                int  a_mode;
        !           196:                struct ucred *a_cred;
        !           197:                struct proc *a_p;
        !           198:        } */ *ap;
        !           199: {
        !           200:        struct vnode *vp = ap->a_vp;
        !           201:        struct iso_node *ip = VTOI(vp);
        !           202:        struct ucred *cred = ap->a_cred;
        !           203:        mode_t mask, mode = ap->a_mode;
        !           204:        register gid_t *gp;
        !           205:        int i, error;
        !           206: 
        !           207:        /*
        !           208:         * Disallow write attempts on read-only file systems;
        !           209:         * unless the file is a socket, fifo, or a block or
        !           210:         * character device resident on the file system.
        !           211:         */
        !           212:        if (mode & VWRITE) {
        !           213:                switch (vp->v_type) {
        !           214:                case VDIR:
        !           215:                case VLNK:
        !           216:                case VREG:
        !           217:                        if (vp->v_mount->mnt_flag & MNT_RDONLY)
        !           218:                                return (EROFS);
        !           219: #if QUOTA
        !           220:                        if ( (error = getinoquota(ip)) )
        !           221:                                return (error);
        !           222: #endif
        !           223:                        break;
        !           224:                default:
        !           225:                        break;
        !           226:                }
        !           227:        }
        !           228: 
        !           229:        /* If immutable bit set, nobody gets to write it. */
        !           230:        if ((mode & VWRITE) && (ip->i_flag & IMMUTABLE))
        !           231:                return (EPERM);
        !           232: 
        !           233:        /* Otherwise, user id 0 always gets access. */
        !           234:        if (cred->cr_uid == 0)
        !           235:                return (0);
        !           236: 
        !           237:        mask = 0;
        !           238: 
        !           239:        /* Otherwise, check the owner. */
        !           240:        if (cred->cr_uid == ip->inode.iso_uid) {
        !           241:                if (mode & VEXEC)
        !           242:                        mask |= S_IXUSR;
        !           243:                if (mode & VREAD)
        !           244:                        mask |= S_IRUSR;
        !           245:                if (mode & VWRITE)
        !           246:                        mask |= S_IWUSR;
        !           247:                return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
        !           248:        }
        !           249: 
        !           250:        /* Otherwise, check the groups. */
        !           251:        for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++)
        !           252:                if (ip->inode.iso_gid == *gp) {
        !           253:                        if (mode & VEXEC)
        !           254:                                mask |= S_IXGRP;
        !           255:                        if (mode & VREAD)
        !           256:                                mask |= S_IRGRP;
        !           257:                        if (mode & VWRITE)
        !           258:                                mask |= S_IWGRP;
        !           259:                        return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
        !           260:                }
        !           261: 
        !           262:        /* Otherwise, check everyone else. */
        !           263:        if (mode & VEXEC)
        !           264:                mask |= S_IXOTH;
        !           265:        if (mode & VREAD)
        !           266:                mask |= S_IROTH;
        !           267:        if (mode & VWRITE)
        !           268:                mask |= S_IWOTH;
        !           269:        return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES);
        !           270: }
        !           271: 
        !           272: int
        !           273: cd9660_getattr(ap)
        !           274:        struct vop_getattr_args /* {
        !           275:                struct vnode *a_vp;
        !           276:                struct vattr *a_vap;
        !           277:                struct ucred *a_cred;
        !           278:                struct proc *a_p;
        !           279:        } */ *ap;
        !           280: 
        !           281: {
        !           282:        struct vnode *vp = ap->a_vp;
        !           283:        register struct vattr *vap = ap->a_vap;
        !           284:        register struct iso_node *ip = VTOI(vp);
        !           285: 
        !           286:        vap->va_fsid    = ip->i_dev;
        !           287:        vap->va_fileid  = ip->i_number;
        !           288: 
        !           289:        vap->va_mode    = ip->inode.iso_mode;
        !           290:        vap->va_nlink   = ip->inode.iso_links;
        !           291:        vap->va_uid     = ip->inode.iso_uid;
        !           292:        vap->va_gid     = ip->inode.iso_gid;
        !           293:        vap->va_atime   = ip->inode.iso_atime;
        !           294:        vap->va_mtime   = ip->inode.iso_mtime;
        !           295:        vap->va_ctime   = ip->inode.iso_ctime;
        !           296:        vap->va_rdev    = ip->inode.iso_rdev;
        !           297: 
        !           298:        vap->va_size    = (u_quad_t) ip->i_size;
        !           299:        if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) {
        !           300:                struct vop_readlink_args rdlnk;
        !           301:                struct iovec aiov;
        !           302:                struct uio auio;
        !           303:                char *cp;
        !           304: 
        !           305:                MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK);
        !           306:                aiov.iov_base = cp;
        !           307:                aiov.iov_len = MAXPATHLEN;
        !           308:                auio.uio_iov = &aiov;
        !           309:                auio.uio_iovcnt = 1;
        !           310:                auio.uio_offset = 0;
        !           311:                auio.uio_rw = UIO_READ;
        !           312:                auio.uio_segflg = UIO_SYSSPACE;
        !           313:                auio.uio_procp = ap->a_p;
        !           314:                auio.uio_resid = MAXPATHLEN;
        !           315:                rdlnk.a_uio = &auio;
        !           316:                rdlnk.a_vp = ap->a_vp;
        !           317:                rdlnk.a_cred = ap->a_cred;
        !           318:                if (cd9660_readlink(&rdlnk) == 0)
        !           319:                        vap->va_size = MAXPATHLEN - auio.uio_resid;
        !           320:                FREE(cp, M_TEMP);
        !           321:        }
        !           322:        vap->va_flags   = 0;
        !           323:        vap->va_gen = 1;
        !           324:        vap->va_blocksize = ip->i_mnt->logical_block_size;
        !           325:        vap->va_bytes   = (u_quad_t) ip->i_size;
        !           326:        vap->va_type    = vp->v_type;
        !           327:        return (0);
        !           328: }
        !           329: 
        !           330: #if ISO_DEFAULT_BLOCK_SIZE >= NBPG
        !           331: #ifdef DEBUG
        !           332: extern int doclusterread;
        !           333: #else
        !           334: #define doclusterread 1
        !           335: #endif
        !           336: #else
        !           337: /* XXX until cluster routines can handle block sizes less than one page */
        !           338: #define doclusterread 0
        !           339: #endif
        !           340: 
        !           341: /*
        !           342:  * Vnode op for reading.
        !           343:  */
        !           344: int
        !           345: cd9660_read(ap)
        !           346:        struct vop_read_args /* {
        !           347:                struct vnode *a_vp;
        !           348:                struct uio *a_uio;
        !           349:                int a_ioflag;
        !           350:                struct ucred *a_cred;
        !           351:        } */ *ap;
        !           352: {
        !           353:        struct vnode *vp = ap->a_vp;
        !           354:        register struct uio *uio = ap->a_uio;
        !           355:        register struct iso_node *ip = VTOI(vp);
        !           356:        register struct iso_mnt *imp;
        !           357:        struct buf *bp;
        !           358:        daddr_t lbn, rablock;
        !           359:        off_t diff;
        !           360:        int rasize, error = 0;
        !           361:        long size, n, on;
        !           362: #ifdef NeXT
        !           363:        int firstpass;
        !           364:        int seq;
        !           365:        int devBlockSize;
        !           366: #endif /* NeXT */
        !           367: 
        !           368:        if (uio->uio_resid == 0)
        !           369:                return (0);
        !           370:        if (uio->uio_offset < 0)
        !           371:                return (EINVAL);
        !           372:        ip->i_flag |= IN_ACCESS;
        !           373:        imp = ip->i_mnt;
        !           374: #ifdef NeXT 
        !           375:        firstpass=TRUE;
        !           376:        VOP_DEVBLOCKSIZE(ip->i_devvp, &devBlockSize);
        !           377: #endif /* NeXT */
        !           378:        do {
        !           379:                lbn = lblkno(imp, uio->uio_offset);
        !           380:                on = blkoff(imp, uio->uio_offset);
        !           381:                n = min((u_int)(imp->logical_block_size - on),
        !           382:                        uio->uio_resid);
        !           383:                diff = (off_t)ip->i_size - uio->uio_offset;
        !           384:                if (diff <= 0)
        !           385:                        return (0);
        !           386:                if (diff < n)
        !           387:                        n = diff;
        !           388:                size = blksize(imp, ip, lbn);
        !           389:                rablock = lbn + 1;
        !           390:                if (doclusterread) {
        !           391:                        if (lblktosize(imp, rablock) <= ip->i_size)
        !           392: #ifdef NeXT
        !           393:                                error = cluster_read(vp, (off_t)ip->i_size,
        !           394:                                   lbn, size, NOCRED, &bp, devBlockSize,
        !           395:                                     firstpass, (uio->uio_resid + on), &seq);
        !           396: #else
        !           397:                                error = cluster_read(vp, (off_t)ip->i_size,
        !           398:                                                     lbn, size, NOCRED, &bp);
        !           399: #endif /* NeXT */
        !           400:                        else
        !           401:                                error = bread(vp, lbn, size, NOCRED, &bp);
        !           402:                } else {
        !           403:                        if (vp->v_lastr + 1 == lbn &&
        !           404:                            lblktosize(imp, rablock) < ip->i_size) {
        !           405:                                rasize = blksize(imp, ip, rablock);
        !           406:                                error = breadn(vp, lbn, size, &rablock,
        !           407:                                               &rasize, 1, NOCRED, &bp);
        !           408:                        } else
        !           409:                                error = bread(vp, lbn, size, NOCRED, &bp);
        !           410:                }
        !           411:                vp->v_lastr = lbn;
        !           412:                n = min(n, size - bp->b_resid);
        !           413:                if (error) {
        !           414:                        brelse(bp);
        !           415:                        return (error);
        !           416:                }
        !           417: 
        !           418:                error = uiomove(bp->b_data + on, (int)n, uio);
        !           419:                if (n + on == imp->logical_block_size ||
        !           420:                    uio->uio_offset == (off_t)ip->i_size)
        !           421:                        bp->b_flags |= B_AGE;
        !           422:                brelse(bp);
        !           423:        firstpass = FALSE;
        !           424:        } while (error == 0 && uio->uio_resid > 0 && n != 0);
        !           425:        return (error);
        !           426: }
        !           427: 
        !           428: /* ARGSUSED */
        !           429: int
        !           430: cd9660_ioctl(ap)
        !           431:        struct vop_ioctl_args /* {
        !           432:                struct vnode *a_vp;
        !           433:                u_long a_command;
        !           434:                caddr_t  a_data;
        !           435:                int  a_fflag;
        !           436:                struct ucred *a_cred;
        !           437:                struct proc *a_p;
        !           438:        } */ *ap;
        !           439: {
        !           440:        printf("You did ioctl for isofs !!\n");
        !           441:        return (ENOTTY);
        !           442: }
        !           443: 
        !           444: /* ARGSUSED */
        !           445: int
        !           446: cd9660_select(ap)
        !           447:        struct vop_select_args /* {
        !           448:                struct vnode *a_vp;
        !           449:                int  a_which;
        !           450:                int  a_fflags;
        !           451:                struct ucred *a_cred;
        !           452:                struct proc *a_p;
        !           453:        } */ *ap;
        !           454: {
        !           455: 
        !           456:        /*
        !           457:         * We should really check to see if I/O is possible.
        !           458:         */
        !           459:        return (1);
        !           460: }
        !           461: 
        !           462: /*
        !           463:  * Mmap a file
        !           464:  *
        !           465:  * NB Currently unsupported.
        !           466:  */
        !           467: /* ARGSUSED */
        !           468: int
        !           469: cd9660_mmap(ap)
        !           470:        struct vop_mmap_args /* {
        !           471:                struct vnode *a_vp;
        !           472:                int  a_fflags;
        !           473:                struct ucred *a_cred;
        !           474:                struct proc *a_p;
        !           475:        } */ *ap;
        !           476: {
        !           477: 
        !           478:        return (EINVAL);
        !           479: }
        !           480: 
        !           481: /*
        !           482:  * Seek on a file
        !           483:  *
        !           484:  * Nothing to do, so just return.
        !           485:  */
        !           486: /* ARGSUSED */
        !           487: int
        !           488: cd9660_seek(ap)
        !           489:        struct vop_seek_args /* {
        !           490:                struct vnode *a_vp;
        !           491:                off_t  a_oldoff;
        !           492:                off_t  a_newoff;
        !           493:                struct ucred *a_cred;
        !           494:        } */ *ap;
        !           495: {
        !           496: 
        !           497:        return (0);
        !           498: }
        !           499: 
        !           500: /*
        !           501:  * Structure for reading directories
        !           502:  */
        !           503: struct isoreaddir {
        !           504:        struct dirent saveent;
        !           505:        struct dirent assocent;
        !           506:        struct dirent current;
        !           507:        off_t saveoff;
        !           508:        off_t assocoff;
        !           509:        off_t curroff;
        !           510:        struct uio *uio;
        !           511:        off_t uio_off;
        !           512:        int eofflag;
        !           513: //     u_long **cookies;
        !           514: //     int *ncookies;
        !           515: };
        !           516: 
        !           517: int
        !           518: iso_uiodir(idp,dp,off)
        !           519:        struct isoreaddir *idp;
        !           520:        struct dirent *dp;
        !           521:        off_t off;
        !           522: {
        !           523:        int error;
        !           524: 
        !           525:        dp->d_name[dp->d_namlen] = 0;
        !           526:        dp->d_reclen = DIRSIZ(dp);
        !           527: 
        !           528:        if (idp->uio->uio_resid < dp->d_reclen) {
        !           529:                idp->eofflag = 0;
        !           530:                return (-1);
        !           531:        }
        !           532: 
        !           533: #if 0
        !           534:        if (idp->cookies) {
        !           535:                if (*idp->ncookies <= 0) {
        !           536:                        idp->eofflag = 0;
        !           537:                        return (-1);
        !           538:                }
        !           539: 
        !           540:                **idp->cookies++ = off;
        !           541:                --*idp->ncookies;
        !           542:        }
        !           543: #endif
        !           544: 
        !           545:        if ( (error = uiomove( (caddr_t)dp, dp->d_reclen, idp->uio )) )
        !           546:                return (error);
        !           547:        idp->uio_off = off;
        !           548:        return (0);
        !           549: }
        !           550: 
        !           551: int
        !           552: iso_shipdir(idp)
        !           553:        struct isoreaddir *idp;
        !           554: {
        !           555:        struct dirent *dp;
        !           556:        int cl, sl, assoc;
        !           557:        int error;
        !           558:        char *cname, *sname;
        !           559: 
        !           560:        cl = idp->current.d_namlen;
        !           561:        cname = idp->current.d_name;
        !           562:        assoc = (cl > 1) && (*cname == ASSOCCHAR );
        !           563:        if (assoc)  {
        !           564:                cl--;
        !           565:                cname++;
        !           566:        }
        !           567: 
        !           568:        dp = &idp->saveent;
        !           569:        sname = dp->d_name;
        !           570:        if (!(sl = dp->d_namlen)) {
        !           571:                dp = &idp->assocent;
        !           572:                sname = dp->d_name + 1;
        !           573:                sl = dp->d_namlen - 1;
        !           574:        }
        !           575:        if (sl > 0) {
        !           576:                if (sl != cl
        !           577:                    || bcmp(sname,cname,sl)) {
        !           578:                        if (idp->assocent.d_namlen) {
        !           579:                                if ( (error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) )
        !           580:                                        return (error);
        !           581:                                idp->assocent.d_namlen = 0;
        !           582:                        }
        !           583:                        if (idp->saveent.d_namlen) {
        !           584:                                if ( (error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) )
        !           585:                                        return (error);
        !           586:                                idp->saveent.d_namlen = 0;
        !           587:                        }
        !           588:                }
        !           589:        }
        !           590:        idp->current.d_reclen = DIRSIZ(&idp->current);
        !           591:        if (assoc) {
        !           592:                idp->assocoff = idp->curroff;
        !           593:                bcopy(&idp->current,&idp->assocent,idp->current.d_reclen);
        !           594:        } else {
        !           595:                idp->saveoff = idp->curroff;
        !           596:                bcopy(&idp->current,&idp->saveent,idp->current.d_reclen);
        !           597:        }
        !           598:        return (0);
        !           599: }
        !           600: 
        !           601: /*
        !           602:  * Vnode op for readdir
        !           603:  */
        !           604: int
        !           605: cd9660_readdir(ap)
        !           606:        struct vop_readdir_args /* {
        !           607:                struct vnodeop_desc *a_desc;
        !           608:                struct vnode *a_vp;
        !           609:                struct uio *a_uio;
        !           610:                struct ucred *a_cred;
        !           611:                int *a_eofflag;
        !           612:                int *a_ncookies;
        !           613:                u_long **a_cookies;
        !           614:        } */ *ap;
        !           615: {
        !           616:        register struct uio *uio = ap->a_uio;
        !           617:        off_t startingOffset = uio->uio_offset;
        !           618:        size_t lost = 0;
        !           619:        struct isoreaddir *idp;
        !           620:        struct vnode *vdp = ap->a_vp;
        !           621:        struct iso_node *dp;
        !           622:        struct iso_mnt *imp;
        !           623:        struct buf *bp = NULL;
        !           624:        struct iso_directory_record *ep;
        !           625:        int entryoffsetinblock;
        !           626:        doff_t endsearch;
        !           627:        u_long bmask;
        !           628:        int error = 0;
        !           629:        int reclen;
        !           630:        u_short namelen;
        !           631: 
        !           632:        dp = VTOI(vdp);
        !           633:        imp = dp->i_mnt;
        !           634:        bmask = imp->im_bmask;
        !           635: 
        !           636:        MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK);
        !           637:        idp->saveent.d_namlen = idp->assocent.d_namlen = 0;
        !           638:        /*
        !           639:         * XXX
        !           640:         * Is it worth trying to figure out the type?
        !           641:         */
        !           642:        idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type =
        !           643:            DT_UNKNOWN;
        !           644:        idp->uio = uio;
        !           645:        idp->eofflag = 1;
        !           646:        idp->curroff = uio->uio_offset;
        !           647: 
        !           648:        if ((entryoffsetinblock = idp->curroff & bmask) &&
        !           649:            (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) {
        !           650:                FREE(idp, M_TEMP);
        !           651:                return (error);
        !           652:        }
        !           653:        endsearch = dp->i_size;
        !           654: 
        !           655:        while (idp->curroff < endsearch) {
        !           656:                /*
        !           657:                 * If offset is on a block boundary,
        !           658:                 * read the next directory block.
        !           659:                 * Release previous if it exists.
        !           660:                 */
        !           661:                if ((idp->curroff & bmask) == 0) {
        !           662:                        if (bp != NULL)
        !           663:                                brelse(bp);
        !           664:                        if ( (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp)) )
        !           665:                                break;
        !           666:                        entryoffsetinblock = 0;
        !           667:                }
        !           668:                /*
        !           669:                 * Get pointer to next entry.
        !           670:                 */
        !           671:                ep = (struct iso_directory_record *)
        !           672:                        ((char *)bp->b_data + entryoffsetinblock);
        !           673: 
        !           674:                reclen = isonum_711(ep->length);
        !           675:                if (reclen == 0) {
        !           676:                        /* skip to next block, if any */
        !           677:                        idp->curroff =
        !           678:                            (idp->curroff & ~bmask) + imp->logical_block_size;
        !           679:                        continue;
        !           680:                }
        !           681: 
        !           682:                if (reclen < ISO_DIRECTORY_RECORD_SIZE) {
        !           683:                        error = EINVAL;
        !           684:                        /* illegal entry, stop */
        !           685:                        break;
        !           686:                }
        !           687: 
        !           688:                if (entryoffsetinblock + reclen > imp->logical_block_size) {
        !           689:                        error = EINVAL;
        !           690:                        /* illegal directory, so stop looking */
        !           691:                        break;
        !           692:                }
        !           693: 
        !           694:                idp->current.d_namlen = isonum_711(ep->name_len);
        !           695: 
        !           696:                if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
        !           697:                        error = EINVAL;
        !           698:                        /* illegal entry, stop */
        !           699:                        break;
        !           700:                }
        !           701: 
        !           702:                if ( isonum_711(ep->flags) & directoryBit )
        !           703:                        idp->current.d_fileno = isodirino(ep, imp);
        !           704:                else
        !           705:                {
        !           706: 
        !           707:                        idp->current.d_fileno = (bp->b_blkno << imp->im_bshift) + entryoffsetinblock;
        !           708: 
        !           709:                }
        !           710: 
        !           711:                idp->curroff += reclen;
        !           712: 
        !           713:                switch (imp->iso_ftype) {
        !           714:                case ISO_FTYPE_RRIP:
        !           715:                        cd9660_rrip_getname(ep,idp->current.d_name, &namelen,
        !           716:                                           &idp->current.d_fileno,imp);
        !           717:                        idp->current.d_namlen = (u_char)namelen;
        !           718:                        if (idp->current.d_namlen)
        !           719:                                error = iso_uiodir(idp,&idp->current,idp->curroff);
        !           720:                        break;
        !           721:                default:        /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */
        !           722:                        strcpy(idp->current.d_name,"..");
        !           723:                        switch (ep->name[0]) {
        !           724:                        case 0:
        !           725:                                idp->current.d_namlen = 1;
        !           726:                                error = iso_uiodir(idp,&idp->current,idp->curroff);
        !           727:                                break;
        !           728:                        case 1:
        !           729:                                idp->current.d_namlen = 2;
        !           730:                                error = iso_uiodir(idp,&idp->current,idp->curroff);
        !           731:                                break;
        !           732:                        default:
        !           733:                                isofntrans(ep->name,idp->current.d_namlen,
        !           734:                                           idp->current.d_name, &namelen,
        !           735:                                           imp->iso_ftype == ISO_FTYPE_9660,
        !           736:                                           isonum_711(ep->flags) & associatedBit);
        !           737:                                idp->current.d_namlen = (u_char)namelen;
        !           738:                                if (imp->iso_ftype == ISO_FTYPE_DEFAULT)
        !           739:                                        error = iso_shipdir(idp);
        !           740:                                else
        !           741:                                        error = iso_uiodir(idp,&idp->current,idp->curroff);
        !           742:                                break;
        !           743:                        }
        !           744:                }
        !           745:                if (error)
        !           746:                        break;
        !           747: 
        !           748:                entryoffsetinblock += reclen;
        !           749:        }
        !           750: 
        !           751:        if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) {
        !           752:                idp->current.d_namlen = 0;
        !           753:                error = iso_shipdir(idp);
        !           754:        }
        !           755: 
        !           756:        if (!error && ap->a_ncookies) {
        !           757:                struct dirent *dp, *dpstart;
        !           758:                off_t bufferOffset;
        !           759:                u_long *cookies;
        !           760:                int ncookies;
        !           761: 
        !           762:                /*
        !           763:                 * Only the NFS server uses cookies, and it loads the
        !           764:                 * directory block into system space, so we can just look at
        !           765:                 * it directly.
        !           766:                 *
        !           767:                 * We assume the entire transfer is done to a single contiguous buffer.
        !           768:                 */
        !           769:                if (uio->uio_segflg != UIO_SYSSPACE || uio->uio_iovcnt != 1)
        !           770:                        panic("ufs_readdir: lost in space");
        !           771:                
        !           772:                /*
        !           773:                 * Make a first pass over the buffer just generated,
        !           774:                 * counting the number of entries:
        !           775:                 */
        !           776:                dpstart = (struct dirent *) (uio->uio_iov->iov_base - (uio->uio_offset - startingOffset));
        !           777:                for (dp = dpstart, bufferOffset = startingOffset, ncookies = 0;
        !           778:                     bufferOffset < uio->uio_offset; ) {
        !           779:                        if (dp->d_reclen == 0)
        !           780:                                break;
        !           781:                        bufferOffset += dp->d_reclen;
        !           782:                        ncookies++;
        !           783:                        dp = (struct dirent *)((caddr_t)dp + dp->d_reclen);
        !           784:                }
        !           785:                lost += uio->uio_offset - bufferOffset;
        !           786:                uio->uio_offset = bufferOffset;
        !           787:                
        !           788:                /*
        !           789:                 * Allocate a buffer to hold the cookies requested:
        !           790:                 */
        !           791:                MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, M_WAITOK);
        !           792:                *ap->a_ncookies = ncookies;
        !           793:                *ap->a_cookies = cookies;
        !           794: 
        !           795:                /*
        !           796:                 * Fill in the offsets for each entry in the buffer just allocated:
        !           797:                 */
        !           798:                for (bufferOffset = startingOffset, dp = dpstart; bufferOffset < uio->uio_offset; ) {
        !           799:                        *(cookies++) = bufferOffset;
        !           800:                        bufferOffset += dp->d_reclen;
        !           801:                        dp = (struct dirent *)((caddr_t)dp + dp->d_reclen);
        !           802:                }
        !           803:        }
        !           804: 
        !           805:        if (error < 0)
        !           806:                error = 0;
        !           807: 
        !           808:        if (bp)
        !           809:                brelse (bp);
        !           810: 
        !           811:        uio->uio_offset = idp->uio_off;
        !           812:        *ap->a_eofflag = idp->eofflag;
        !           813: 
        !           814:        FREE(idp, M_TEMP);
        !           815: 
        !           816:        return (error);
        !           817: }
        !           818: 
        !           819: /*
        !           820:  * Return target name of a symbolic link
        !           821:  * Shouldn't we get the parent vnode and read the data from there?
        !           822:  * This could eventually result in deadlocks in cd9660_lookup.
        !           823:  * But otherwise the block read here is in the block buffer two times.
        !           824:  */
        !           825: typedef struct iso_directory_record ISODIR;
        !           826: typedef struct iso_node             ISONODE;
        !           827: typedef struct iso_mnt              ISOMNT;
        !           828: int
        !           829: cd9660_readlink(ap)
        !           830:        struct vop_readlink_args /* {
        !           831:                struct vnode *a_vp;
        !           832:                struct uio *a_uio;
        !           833:                struct ucred *a_cred;
        !           834:        } */ *ap;
        !           835: {
        !           836:        ISONODE *ip;
        !           837:        ISODIR  *dirp;
        !           838:        ISOMNT  *imp;
        !           839:        struct  buf *bp;
        !           840:        struct  uio *uio;
        !           841:        u_short symlen;
        !           842:        int     error;
        !           843:        char    *symname;
        !           844: 
        !           845:        ip  = VTOI(ap->a_vp);
        !           846:        imp = ip->i_mnt;
        !           847:        uio = ap->a_uio;
        !           848: 
        !           849:        if (imp->iso_ftype != ISO_FTYPE_RRIP)
        !           850:                return (EINVAL);
        !           851: 
        !           852:        /*
        !           853:         * Get parents directory record block that this inode included.
        !           854:         */
        !           855:        error = bread(imp->im_devvp,
        !           856:                          (ip->i_number >> imp->im_bshift),
        !           857:                      imp->logical_block_size, NOCRED, &bp);
        !           858:        if (error) {
        !           859:                brelse(bp);
        !           860:                return (EINVAL);
        !           861:        }
        !           862: 
        !           863:        /*
        !           864:         * Setup the directory pointer for this inode
        !           865:         */
        !           866:        dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask));
        !           867: 
        !           868:        /*
        !           869:         * Just make sure, we have a right one....
        !           870:         *   1: Check not cross boundary on block
        !           871:         */
        !           872:        if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length)
        !           873:            > imp->logical_block_size) {
        !           874:                brelse(bp);
        !           875:                return (EINVAL);
        !           876:        }
        !           877: 
        !           878:        /*
        !           879:         * Now get a buffer
        !           880:         * Abuse a namei buffer for now.
        !           881:         */
        !           882:        if (uio->uio_segflg == UIO_SYSSPACE)
        !           883:                symname = uio->uio_iov->iov_base;
        !           884:        else
        !           885:                MALLOC_ZONE(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
        !           886:        
        !           887:        /*
        !           888:         * Ok, we just gathering a symbolic name in SL record.
        !           889:         */
        !           890:        if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) {
        !           891:                if (uio->uio_segflg != UIO_SYSSPACE)
        !           892:                        FREE_ZONE(symname, MAXPATHLEN, M_NAMEI);
        !           893:                brelse(bp);
        !           894:                return (EINVAL);
        !           895:        }
        !           896:        /*
        !           897:         * Don't forget before you leave from home ;-)
        !           898:         */
        !           899:        brelse(bp);
        !           900: 
        !           901:        /*
        !           902:         * return with the symbolic name to caller's.
        !           903:         */
        !           904:        if (uio->uio_segflg != UIO_SYSSPACE) {
        !           905:                error = uiomove(symname, symlen, uio);
        !           906:                FREE_ZONE(symname, MAXPATHLEN, M_NAMEI);
        !           907:                return (error);
        !           908:        }
        !           909:        uio->uio_resid -= symlen;
        !           910:        uio->uio_iov->iov_base += symlen;
        !           911:        uio->uio_iov->iov_len -= symlen;
        !           912:        return (0);
        !           913: }
        !           914: 
        !           915: /*
        !           916:  * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually
        !           917:  * done. If a buffer has been saved in anticipation of a CREATE, delete it.
        !           918:  */
        !           919: int
        !           920: cd9660_abortop(ap)
        !           921:        struct vop_abortop_args /* {
        !           922:                struct vnode *a_dvp;
        !           923:                struct componentname *a_cnp;
        !           924:        } */ *ap;
        !           925: {
        !           926:        if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF)
        !           927:                FREE_ZONE(ap->a_cnp->cn_pnbuf, ap->a_cnp->cn_pnlen, M_NAMEI);
        !           928:        return (0);
        !           929: }
        !           930: 
        !           931: /*
        !           932:  * Lock an inode.
        !           933:  */
        !           934: int
        !           935: cd9660_lock(ap)
        !           936:        struct vop_lock_args /* {
        !           937:                struct vnode *a_vp;
        !           938:                int a_flags;
        !           939:                struct proc *a_p;
        !           940:        } */ *ap;
        !           941: {
        !           942:        struct vnode *vp = ap->a_vp;
        !           943: 
        !           944:        if (VTOI(vp) == (struct inode *) NULL)
        !           945:                panic ("cd9660 inode in vnode is null\n");
        !           946:        return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock,ap->a_p));
        !           947: }
        !           948: 
        !           949: /*
        !           950:  * Unlock an inode.
        !           951:  */
        !           952: int
        !           953: cd9660_unlock(ap)
        !           954:        struct vop_unlock_args /* {
        !           955:                struct vnode *a_vp;
        !           956:                int a_flags;
        !           957:                struct proc *a_p;
        !           958:        } */ *ap;
        !           959: {
        !           960:        struct vnode *vp = ap->a_vp;
        !           961: 
        !           962:        return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, &vp->v_interlock,ap->a_p));
        !           963: 
        !           964: }
        !           965: 
        !           966: /*
        !           967:  * Calculate the logical to physical mapping if not done already,
        !           968:  * then call the device strategy routine.
        !           969:  */
        !           970: int
        !           971: cd9660_strategy(ap)
        !           972:        struct vop_strategy_args /* {
        !           973:                struct buf *a_bp;
        !           974:        } */ *ap;
        !           975: {
        !           976:        register struct buf *bp = ap->a_bp;
        !           977:        register struct vnode *vp = bp->b_vp;
        !           978:        register struct iso_node *ip;
        !           979:        int error;
        !           980: 
        !           981:        ip = VTOI(vp);
        !           982:        if (vp->v_type == VBLK || vp->v_type == VCHR)
        !           983:                panic("cd9660_strategy: spec");
        !           984:        if (bp->b_blkno == bp->b_lblkno) {
        !           985:                if ( (error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) ) {
        !           986:                        bp->b_error = error;
        !           987:                        bp->b_flags |= B_ERROR;
        !           988:                        biodone(bp);
        !           989:                        return (error);
        !           990:                }
        !           991:                if ((long)bp->b_blkno == -1)
        !           992:                        clrbuf(bp);
        !           993:        }
        !           994:        if ((long)bp->b_blkno == -1) {
        !           995:                biodone(bp);
        !           996:                return (0);
        !           997:        }
        !           998:        vp = ip->i_devvp;
        !           999:        bp->b_dev = vp->v_rdev;
        !          1000:        VOCALL (vp->v_op, VOFFSET(vop_strategy), ap);
        !          1001:        return (0);
        !          1002: }
        !          1003: 
        !          1004: /*
        !          1005:  * Print out the contents of an inode.
        !          1006:  */
        !          1007: int
        !          1008: cd9660_print(ap)
        !          1009:        struct vop_print_args /* {
        !          1010:                struct vnode *a_vp;
        !          1011:        } */ *ap;
        !          1012: {
        !          1013: 
        !          1014:        printf("tag VT_ISOFS, isofs vnode\n");
        !          1015:        return (0);
        !          1016: }
        !          1017: 
        !          1018: /*
        !          1019:  * Check for a locked inode.
        !          1020:  */
        !          1021: int
        !          1022: cd9660_islocked(ap)
        !          1023:        struct vop_islocked_args /* {
        !          1024:                struct vnode *a_vp;
        !          1025:        } */ *ap;
        !          1026: {
        !          1027: 
        !          1028:        return (lockstatus(&VTOI(ap->a_vp)->i_lock));
        !          1029: }
        !          1030: 
        !          1031: /*
        !          1032:  * Return POSIX pathconf information applicable to cd9660 filesystems.
        !          1033:  */
        !          1034: int
        !          1035: cd9660_pathconf(ap)
        !          1036:        struct vop_pathconf_args /* {
        !          1037:                struct vnode *a_vp;
        !          1038:                int a_name;
        !          1039:                register_t *a_retval;
        !          1040:        } */ *ap;
        !          1041: {
        !          1042: 
        !          1043:        switch (ap->a_name) {
        !          1044:        case _PC_LINK_MAX:
        !          1045:                *ap->a_retval = 1;
        !          1046:                return (0);
        !          1047:        case _PC_NAME_MAX:
        !          1048:                if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP)
        !          1049:                        *ap->a_retval = NAME_MAX;
        !          1050:                else
        !          1051:                        *ap->a_retval = 37;
        !          1052:                return (0);
        !          1053:        case _PC_PATH_MAX:
        !          1054:                *ap->a_retval = PATH_MAX;
        !          1055:                return (0);
        !          1056:        case _PC_PIPE_BUF:
        !          1057:                *ap->a_retval = PIPE_BUF;
        !          1058:                return (0);
        !          1059:        case _PC_CHOWN_RESTRICTED:
        !          1060:                *ap->a_retval = 1;
        !          1061:                return (0);
        !          1062:        case _PC_NO_TRUNC:
        !          1063:                *ap->a_retval = 1;
        !          1064:                return (0);
        !          1065:        default:
        !          1066:                return (EINVAL);
        !          1067:        }
        !          1068:        /* NOTREACHED */
        !          1069: }
        !          1070: 
        !          1071: /*
        !          1072:  * Unsupported operation
        !          1073:  */
        !          1074: int
        !          1075: cd9660_enotsupp()
        !          1076: {
        !          1077: 
        !          1078:        return (EOPNOTSUPP);
        !          1079: }
        !          1080: /* Pagein  */
        !          1081: int
        !          1082: cd9660_pagein(ap)
        !          1083:        struct vop_pagein_args /* {
        !          1084:                struct vnode *a_vp;
        !          1085:                struct uio *a_uio;
        !          1086:                int a_ioflag;
        !          1087:                struct ucred *a_cred;
        !          1088:        } */ *ap;
        !          1089: {
        !          1090:        /* pass thru to read */ 
        !          1091:        return (VOP_READ(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
        !          1092: }
        !          1093: 
        !          1094: /* Pageout  */
        !          1095: int
        !          1096: cd9660_pageout(ap)
        !          1097:        struct vop_pageout_args /* {
        !          1098:                struct vnode *a_vp;
        !          1099:                struct uio *a_uio;
        !          1100:                int a_ioflag;
        !          1101:                struct ucred *a_cred;
        !          1102:        } */ *ap;
        !          1103: {
        !          1104:        /* pass thru to write */ 
        !          1105:        return (VOP_WRITE(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
        !          1106: }
        !          1107: 
        !          1108: /*  
        !          1109:  * cd9660_remove - not possible to remove a file from iso cds
        !          1110:  *  
        !          1111:  * Locking policy: a_dvp and vp locked on entry, unlocked on exit
        !          1112:  */ 
        !          1113: int 
        !          1114: cd9660_remove(ap)
        !          1115:     struct vop_remove_args      /* { struct vnode *a_dvp; struct vnode *a_vp;
        !          1116:         struct componentname *a_cnp; } */ *ap;  
        !          1117: {   
        !          1118:     if (ap->a_dvp == ap->a_vp)
        !          1119:                 vrele(ap->a_vp);
        !          1120:         else
        !          1121:                 vput(ap->a_vp);
        !          1122:        vput(ap->a_dvp);
        !          1123: 
        !          1124:     return (EROFS);
        !          1125: }   
        !          1126: 
        !          1127: 
        !          1128: /*  
        !          1129:  * cd9660_rmdir - not possible to remove a directory from iso cds
        !          1130:  *  
        !          1131:  * Locking policy: a_dvp and vp locked on entry, unlocked on exit
        !          1132:  */ 
        !          1133: int 
        !          1134: cd9660_rmdir(ap)
        !          1135:     struct vop_rmdir_args      /* { struct vnode *a_dvp; struct vnode *a_vp;
        !          1136:         struct componentname *a_cnp; } */ *ap;  
        !          1137: {   
        !          1138:     (void) nop_rmdir(ap);
        !          1139:     return (EROFS);
        !          1140: }   
        !          1141: 
        !          1142: /*
        !          1143: 
        !          1144: #
        !          1145: #% getattrlist vp      = = =
        !          1146: #
        !          1147:  vop_getattrlist {
        !          1148:      IN struct vnode *vp;
        !          1149:      IN struct attrlist *alist;
        !          1150:      INOUT struct uio *uio;
        !          1151:      IN struct ucred *cred;
        !          1152:      IN struct proc *p;
        !          1153:  };
        !          1154: 
        !          1155:  */
        !          1156: int
        !          1157: cd9660_getattrlist(ap)
        !          1158:        struct vop_getattrlist_args /* {
        !          1159:        struct vnode *a_vp;
        !          1160:        struct attrlist *a_alist
        !          1161:        struct uio *a_uio;
        !          1162:        struct ucred *a_cred;
        !          1163:        struct proc *a_p;
        !          1164:        } */ *ap;
        !          1165: {
        !          1166:     struct attrlist *alist = ap->a_alist;
        !          1167:     int fixedblocksize;
        !          1168:     int attrblocksize;
        !          1169:     int attrbufsize;
        !          1170:     void *attrbufptr;
        !          1171:     void *attrptr;
        !          1172:     void *varptr;
        !          1173:     int error = 0;
        !          1174: 
        !          1175:        if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT) ||
        !          1176:         ((alist->commonattr & ~ATTR_CMN_VALIDMASK) != 0) ||
        !          1177:         ((alist->volattr & ~ATTR_VOL_VALIDMASK) != 0) ||
        !          1178:         ((alist->dirattr & ~ATTR_DIR_VALIDMASK) != 0) ||
        !          1179:         ((alist->fileattr & ~ATTR_FILE_VALIDMASK) != 0) ||
        !          1180:         ((alist->forkattr & ~ATTR_FORK_VALIDMASK) != 0)) {
        !          1181:                return EINVAL;
        !          1182:        };
        !          1183: 
        !          1184:        /* 
        !          1185:         * Requesting volume information requires setting the ATTR_VOL_INFO bit and
        !          1186:         * volume info requests are mutually exclusive with all other info requests:
        !          1187:         */
        !          1188:        if ((alist->volattr != 0) &&
        !          1189:                (((alist->volattr & ATTR_VOL_INFO) == 0) ||
        !          1190:                (alist->dirattr != 0) || 
        !          1191:                (alist->fileattr != 0) || 
        !          1192:                (alist->forkattr != 0) )) {
        !          1193:         return EINVAL;
        !          1194:        };
        !          1195: 
        !          1196:        /*
        !          1197:         * Reject requests for unsupported options for now:
        !          1198:         */
        !          1199:        if (alist->volattr & ATTR_VOL_MOUNTPOINT) return EINVAL;
        !          1200:        if (alist->commonattr & (ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST)) return EINVAL;
        !          1201:        if (alist->fileattr &
        !          1202:                (ATTR_FILE_FILETYPE |
        !          1203:                 ATTR_FILE_FORKCOUNT |
        !          1204:                 ATTR_FILE_FORKLIST |
        !          1205:                 ATTR_FILE_DATAEXTENTS |
        !          1206:                 ATTR_FILE_RSRCEXTENTS)) {
        !          1207:                return EINVAL;
        !          1208:        };
        !          1209: 
        !          1210: 
        !          1211:     fixedblocksize = attrcalcsize(alist);
        !          1212:     attrblocksize = fixedblocksize + (sizeof(u_long));                                                 /* u_long for length longword */
        !          1213:     if (alist->commonattr & ATTR_CMN_NAME) attrblocksize += NAME_MAX;
        !          1214:     if (alist->commonattr & ATTR_CMN_NAMEDATTRLIST) attrblocksize += 0;                        /* XXX PPD */
        !          1215:     if (alist->volattr & ATTR_VOL_MOUNTPOINT) attrblocksize += PATH_MAX;
        !          1216:     if (alist->volattr & ATTR_VOL_NAME) attrblocksize += NAME_MAX;
        !          1217:     if (alist->fileattr & ATTR_FILE_FORKLIST) attrblocksize += 0;                              /* XXX PPD */
        !          1218: 
        !          1219:     attrbufsize = MIN(ap->a_uio->uio_resid, attrblocksize);
        !          1220:     MALLOC(attrbufptr, void *, attrblocksize, M_TEMP, M_WAITOK);
        !          1221:     attrptr = attrbufptr;
        !          1222:     *((u_long *)attrptr) = 0;                                                                  /* Set buffer length in case of errors */
        !          1223:     ++((u_long *)attrptr);                                                                             /* Reserve space for length field */
        !          1224:     varptr = ((char *)attrptr) + fixedblocksize;                               /* Point to variable-length storage */
        !          1225: 
        !          1226:        packattrblk(alist, ap->a_vp, &attrptr, &varptr);
        !          1227: 
        !          1228:     *((u_long *)attrbufptr) = (varptr - attrbufptr);           /* Store length of fixed + var block */
        !          1229:     attrbufsize = MIN(attrbufsize, varptr - attrbufptr);       /* Don't copy out more data than was generated */
        !          1230: 
        !          1231:     error = uiomove((caddr_t)attrbufptr, attrbufsize, ap->a_uio);
        !          1232: 
        !          1233:     FREE(attrbufptr, M_TEMP);
        !          1234: 
        !          1235:     return error;
        !          1236: }
        !          1237: 
        !          1238: /*
        !          1239:  * Global vfs data structures for isofs
        !          1240:  */
        !          1241: #define cd9660_create \
        !          1242:        ((int (*) __P((struct  vop_create_args *)))err_create)
        !          1243: #define cd9660_mknod ((int (*) __P((struct  vop_mknod_args *)))err_mknod)
        !          1244: #define cd9660_setattr \
        !          1245:        ((int (*) __P((struct  vop_setattr_args *)))cd9660_enotsupp)
        !          1246: #define cd9660_write ((int (*) __P((struct  vop_write_args *)))cd9660_enotsupp)
        !          1247: #ifdef NFSSERVER
        !          1248: int    lease_check __P((struct vop_lease_args *));
        !          1249: #define        cd9660_lease_check lease_check
        !          1250: #else
        !          1251: #define        cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop)
        !          1252: #endif
        !          1253: #define cd9660_fsync ((int (*) __P((struct  vop_fsync_args *)))nullop)
        !          1254: #define cd9660_rename \
        !          1255:        ((int (*) __P((struct  vop_rename_args *)))err_rename)
        !          1256: #define cd9660_link ((int (*) __P((struct  vop_link_args *)))err_link)
        !          1257: #define cd9660_mkdir ((int (*) __P((struct  vop_mkdir_args *)))err_mkdir)
        !          1258: #define cd9660_symlink \
        !          1259:        ((int (*) __P((struct vop_symlink_args *)))err_symlink)
        !          1260: #define cd9660_advlock \
        !          1261:        ((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp)
        !          1262: #define cd9660_valloc ((int(*) __P(( \
        !          1263:                struct vnode *pvp, \
        !          1264:                int mode, \
        !          1265:                struct ucred *cred, \
        !          1266:                struct vnode **vpp))) cd9660_enotsupp)
        !          1267: #define cd9660_vfree ((int (*) __P((struct  vop_vfree_args *)))cd9660_enotsupp)
        !          1268: #define cd9660_truncate \
        !          1269:        ((int (*) __P((struct  vop_truncate_args *)))cd9660_enotsupp)
        !          1270: #define cd9660_update \
        !          1271:        ((int (*) __P((struct  vop_update_args *)))cd9660_enotsupp)
        !          1272: #define cd9660_bwrite \
        !          1273:        ((int (*) __P((struct  vop_bwrite_args *)))cd9660_enotsupp)
        !          1274: 
        !          1275: /*
        !          1276:  * Global vfs data structures for cd9660
        !          1277:  */
        !          1278: int (**cd9660_vnodeop_p)();
        !          1279: struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = {
        !          1280:        { &vop_default_desc, vn_default_error },
        !          1281:        { &vop_lookup_desc, cd9660_lookup },    /* lookup */
        !          1282:        { &vop_create_desc, cd9660_create },    /* create */
        !          1283:        { &vop_mknod_desc, cd9660_mknod },      /* mknod */
        !          1284:        { &vop_open_desc, cd9660_open },        /* open */
        !          1285:        { &vop_close_desc, cd9660_close },      /* close */
        !          1286:        { &vop_access_desc, cd9660_access },    /* access */
        !          1287:        { &vop_getattr_desc, cd9660_getattr },  /* getattr */
        !          1288:        { &vop_setattr_desc, cd9660_setattr },  /* setattr */
        !          1289:        { &vop_read_desc, cd9660_read },        /* read */
        !          1290:        { &vop_write_desc, cd9660_write },      /* write */
        !          1291:        { &vop_lease_desc, cd9660_lease_check },/* lease */
        !          1292:        { &vop_ioctl_desc, cd9660_ioctl },      /* ioctl */
        !          1293:        { &vop_select_desc, cd9660_select },    /* select */
        !          1294:        { &vop_mmap_desc, cd9660_mmap },        /* mmap */
        !          1295:        { &vop_fsync_desc, cd9660_fsync },      /* fsync */
        !          1296:        { &vop_seek_desc, cd9660_seek },        /* seek */
        !          1297:        { &vop_remove_desc, cd9660_remove },    /* remove */
        !          1298:        { &vop_link_desc, cd9660_link },        /* link */
        !          1299:        { &vop_rename_desc, cd9660_rename },    /* rename */
        !          1300:        { &vop_mkdir_desc, cd9660_mkdir },      /* mkdir */
        !          1301:        { &vop_rmdir_desc, cd9660_rmdir },      /* rmdir */
        !          1302:        { &vop_symlink_desc, cd9660_symlink },  /* symlink */
        !          1303:        { &vop_readdir_desc, cd9660_readdir },  /* readdir */
        !          1304:        { &vop_readlink_desc, cd9660_readlink },/* readlink */
        !          1305:        { &vop_abortop_desc, cd9660_abortop },  /* abortop */
        !          1306:        { &vop_inactive_desc, cd9660_inactive },/* inactive */
        !          1307:        { &vop_reclaim_desc, cd9660_reclaim },  /* reclaim */
        !          1308:        { &vop_lock_desc, cd9660_lock },        /* lock */
        !          1309:        { &vop_unlock_desc, cd9660_unlock },    /* unlock */
        !          1310:        { &vop_bmap_desc, cd9660_bmap },        /* bmap */
        !          1311:        { &vop_strategy_desc, cd9660_strategy },/* strategy */
        !          1312:        { &vop_print_desc, cd9660_print },      /* print */
        !          1313:        { &vop_islocked_desc, cd9660_islocked },/* islocked */
        !          1314:        { &vop_pathconf_desc, cd9660_pathconf },/* pathconf */
        !          1315:        { &vop_advlock_desc, cd9660_advlock },  /* advlock */
        !          1316:        { &vop_blkatoff_desc, cd9660_blkatoff },/* blkatoff */
        !          1317:        { &vop_valloc_desc, cd9660_valloc },    /* valloc */
        !          1318:        { &vop_vfree_desc, cd9660_vfree },      /* vfree */
        !          1319:        { &vop_truncate_desc, cd9660_truncate },/* truncate */
        !          1320:        { &vop_update_desc, cd9660_update },    /* update */
        !          1321:        { &vop_bwrite_desc, vn_bwrite },
        !          1322:        { &vop_pagein_desc, cd9660_pagein },            /* Pagein */
        !          1323:        { &vop_pageout_desc, cd9660_pageout },          /* Pageout */
        !          1324:        { &vop_getattrlist_desc, cd9660_getattrlist },  /* getattrlist */
        !          1325:        { (struct vnodeop_desc*)NULL, (int(*)())NULL }
        !          1326: };
        !          1327: struct vnodeopv_desc cd9660_vnodeop_opv_desc =
        !          1328:        { &cd9660_vnodeop_p, cd9660_vnodeop_entries };
        !          1329: 
        !          1330: /*
        !          1331:  * Special device vnode ops
        !          1332:  */
        !          1333: int (**cd9660_specop_p)();
        !          1334: struct vnodeopv_entry_desc cd9660_specop_entries[] = {
        !          1335:        { &vop_default_desc, vn_default_error },
        !          1336:        { &vop_lookup_desc, spec_lookup },      /* lookup */
        !          1337:        { &vop_create_desc, spec_create },      /* create */
        !          1338:        { &vop_mknod_desc, spec_mknod },        /* mknod */
        !          1339:        { &vop_open_desc, spec_open },          /* open */
        !          1340:        { &vop_close_desc, spec_close },        /* close */
        !          1341:        { &vop_access_desc, cd9660_access },    /* access */
        !          1342:        { &vop_getattr_desc, cd9660_getattr },  /* getattr */
        !          1343:        { &vop_setattr_desc, cd9660_setattr },  /* setattr */
        !          1344:        { &vop_read_desc, spec_read },          /* read */
        !          1345:        { &vop_write_desc, spec_write },        /* write */
        !          1346:        { &vop_lease_desc, spec_lease_check },  /* lease */
        !          1347:        { &vop_ioctl_desc, spec_ioctl },        /* ioctl */
        !          1348:        { &vop_select_desc, spec_select },      /* select */
        !          1349:        { &vop_mmap_desc, spec_mmap },          /* mmap */
        !          1350:        { &vop_fsync_desc, spec_fsync },        /* fsync */
        !          1351:        { &vop_seek_desc, spec_seek },          /* seek */
        !          1352:        { &vop_remove_desc, spec_remove },      /* remove */
        !          1353:        { &vop_link_desc, spec_link },          /* link */
        !          1354:        { &vop_rename_desc, spec_rename },      /* rename */
        !          1355:        { &vop_mkdir_desc, spec_mkdir },        /* mkdir */
        !          1356:        { &vop_rmdir_desc, spec_rmdir },        /* rmdir */
        !          1357:        { &vop_symlink_desc, spec_symlink },    /* symlink */
        !          1358:        { &vop_readdir_desc, spec_readdir },    /* readdir */
        !          1359:        { &vop_readlink_desc, spec_readlink },  /* readlink */
        !          1360:        { &vop_abortop_desc, spec_abortop },    /* abortop */
        !          1361:        { &vop_inactive_desc, cd9660_inactive },/* inactive */
        !          1362:        { &vop_reclaim_desc, cd9660_reclaim },  /* reclaim */
        !          1363:        { &vop_lock_desc, cd9660_lock },        /* lock */
        !          1364:        { &vop_unlock_desc, cd9660_unlock },    /* unlock */
        !          1365:        { &vop_bmap_desc, spec_bmap },          /* bmap */
        !          1366:        { &vop_strategy_desc, spec_strategy },  /* strategy */
        !          1367:        { &vop_print_desc, cd9660_print },      /* print */
        !          1368:        { &vop_islocked_desc, cd9660_islocked },/* islocked */
        !          1369:        { &vop_pathconf_desc, spec_pathconf },  /* pathconf */
        !          1370:        { &vop_advlock_desc, spec_advlock },    /* advlock */
        !          1371:        { &vop_blkatoff_desc, spec_blkatoff },  /* blkatoff */
        !          1372:        { &vop_valloc_desc, spec_valloc },      /* valloc */
        !          1373:        { &vop_vfree_desc, spec_vfree },        /* vfree */
        !          1374:        { &vop_truncate_desc, spec_truncate },  /* truncate */
        !          1375:        { &vop_update_desc, cd9660_update },    /* update */
        !          1376:        { &vop_bwrite_desc, vn_bwrite },
        !          1377: #ifdef NeXT
        !          1378:        { &vop_devblocksize_desc, spec_devblocksize },  /* devblocksize */
        !          1379: #endif /* NeXT */
        !          1380:        { &vop_pagein_desc, cd9660_pagein },            /* Pagein */
        !          1381:        { &vop_pageout_desc, cd9660_pageout },          /* Pageout */
        !          1382:        { (struct vnodeop_desc*)NULL, (int(*)())NULL }
        !          1383: };
        !          1384: struct vnodeopv_desc cd9660_specop_opv_desc =
        !          1385:        { &cd9660_specop_p, cd9660_specop_entries };
        !          1386: 
        !          1387: #ifdef FIFO
        !          1388: int (**cd9660_fifoop_p)();
        !          1389: struct vnodeopv_entry_desc cd9660_fifoop_entries[] = {
        !          1390:        { &vop_default_desc, vn_default_error },
        !          1391:        { &vop_lookup_desc, fifo_lookup },      /* lookup */
        !          1392:        { &vop_create_desc, fifo_create },      /* create */
        !          1393:        { &vop_mknod_desc, fifo_mknod },        /* mknod */
        !          1394:        { &vop_open_desc, fifo_open },          /* open */
        !          1395:        { &vop_close_desc, fifo_close },        /* close */
        !          1396:        { &vop_access_desc, cd9660_access },    /* access */
        !          1397:        { &vop_getattr_desc, cd9660_getattr },  /* getattr */
        !          1398:        { &vop_setattr_desc, cd9660_setattr },  /* setattr */
        !          1399:        { &vop_read_desc, fifo_read },          /* read */
        !          1400:        { &vop_write_desc, fifo_write },        /* write */
        !          1401:        { &vop_lease_desc, fifo_lease_check },  /* lease */
        !          1402:        { &vop_ioctl_desc, fifo_ioctl },        /* ioctl */
        !          1403:        { &vop_select_desc, fifo_select },      /* select */
        !          1404:        { &vop_mmap_desc, fifo_mmap },          /* mmap */
        !          1405:        { &vop_fsync_desc, fifo_fsync },        /* fsync */
        !          1406:        { &vop_seek_desc, fifo_seek },          /* seek */
        !          1407:        { &vop_remove_desc, fifo_remove },      /* remove */
        !          1408:        { &vop_link_desc, fifo_link }   ,       /* link */
        !          1409:        { &vop_rename_desc, fifo_rename },      /* rename */
        !          1410:        { &vop_mkdir_desc, fifo_mkdir },        /* mkdir */
        !          1411:        { &vop_rmdir_desc, fifo_rmdir },        /* rmdir */
        !          1412:        { &vop_symlink_desc, fifo_symlink },    /* symlink */
        !          1413:        { &vop_readdir_desc, fifo_readdir },    /* readdir */
        !          1414:        { &vop_readlink_desc, fifo_readlink },  /* readlink */
        !          1415:        { &vop_abortop_desc, fifo_abortop },    /* abortop */
        !          1416:        { &vop_inactive_desc, cd9660_inactive },/* inactive */
        !          1417:        { &vop_reclaim_desc, cd9660_reclaim },  /* reclaim */
        !          1418:        { &vop_lock_desc, cd9660_lock },        /* lock */
        !          1419:        { &vop_unlock_desc, cd9660_unlock },    /* unlock */
        !          1420:        { &vop_bmap_desc, fifo_bmap },          /* bmap */
        !          1421:        { &vop_strategy_desc, fifo_strategy },  /* strategy */
        !          1422:        { &vop_print_desc, cd9660_print },      /* print */
        !          1423:        { &vop_islocked_desc, cd9660_islocked },/* islocked */
        !          1424:        { &vop_pathconf_desc, fifo_pathconf },  /* pathconf */
        !          1425:        { &vop_advlock_desc, fifo_advlock },    /* advlock */
        !          1426:        { &vop_blkatoff_desc, fifo_blkatoff },  /* blkatoff */
        !          1427:        { &vop_valloc_desc, fifo_valloc },      /* valloc */
        !          1428:        { &vop_vfree_desc, fifo_vfree },        /* vfree */
        !          1429:        { &vop_truncate_desc, fifo_truncate },  /* truncate */
        !          1430:        { &vop_update_desc, cd9660_update },    /* update */
        !          1431:        { &vop_bwrite_desc, vn_bwrite },
        !          1432:        { &vop_pagein_desc, cd9660_pagein },            /* Pagein */
        !          1433:        { &vop_pageout_desc, cd9660_pageout },          /* Pageout */
        !          1434:        { (struct vnodeop_desc*)NULL, (int(*)())NULL }
        !          1435: };
        !          1436: struct vnodeopv_desc cd9660_fifoop_opv_desc =
        !          1437:        { &cd9660_fifoop_p, cd9660_fifoop_entries };
        !          1438: #endif /* FIFO */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.