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

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)
1.1.1.2 ! root     1247: #if NFSSERVER
1.1       root     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: 
1.1.1.2 ! root     1387: #if FIFO
1.1       root     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.