Annotation of XNU/bsd/isofs/cd9660/cd9660_vnops.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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