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

Annotation of sys/isofs/cd9660/cd9660_vfsops.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: cd9660_vfsops.c,v 1.46 2007/06/08 05:35:32 deraadt Exp $      */
                      2: /*     $NetBSD: cd9660_vfsops.c,v 1.26 1997/06/13 15:38:58 pk Exp $    */
                      3:
                      4: /*-
                      5:  * Copyright (c) 1994
                      6:  *     The Regents of the University of California.  All rights reserved.
                      7:  *
                      8:  * This code is derived from software contributed to Berkeley
                      9:  * by Pace Willisson (pace@blitz.com).  The Rock Ridge Extension
                     10:  * Support code is derived from software contributed to Berkeley
                     11:  * by Atsushi Murai (amurai@spec.co.jp).
                     12:  *
                     13:  * Redistribution and use in source and binary forms, with or without
                     14:  * modification, are permitted provided that the following conditions
                     15:  * are met:
                     16:  * 1. Redistributions of source code must retain the above copyright
                     17:  *    notice, this list of conditions and the following disclaimer.
                     18:  * 2. Redistributions in binary form must reproduce the above copyright
                     19:  *    notice, this list of conditions and the following disclaimer in the
                     20:  *    documentation and/or other materials provided with the distribution.
                     21:  * 3. Neither the name of the University nor the names of its contributors
                     22:  *    may be used to endorse or promote products derived from this software
                     23:  *    without specific prior written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     35:  * SUCH DAMAGE.
                     36:  *
                     37:  *     @(#)cd9660_vfsops.c     8.9 (Berkeley) 12/5/94
                     38:  */
                     39:
                     40: #include <sys/param.h>
                     41: #include <sys/systm.h>
                     42: #include <sys/namei.h>
                     43: #include <sys/proc.h>
                     44: #include <sys/kernel.h>
                     45: #include <sys/vnode.h>
                     46: #include <miscfs/specfs/specdev.h>
                     47: #include <sys/mount.h>
                     48: #include <sys/buf.h>
                     49: #include <sys/file.h>
                     50: #include <sys/disklabel.h>
                     51: #include <sys/ioctl.h>
                     52: #include <sys/cdio.h>
                     53: #include <sys/conf.h>
                     54: #include <sys/errno.h>
                     55: #include <sys/malloc.h>
                     56: #include <sys/stat.h>
                     57:
                     58: #include <isofs/cd9660/iso.h>
                     59: #include <isofs/cd9660/cd9660_extern.h>
                     60: #include <isofs/cd9660/iso_rrip.h>
                     61: #include <isofs/cd9660/cd9660_node.h>
                     62:
                     63: const struct vfsops cd9660_vfsops = {
                     64:        cd9660_mount,
                     65:        cd9660_start,
                     66:        cd9660_unmount,
                     67:        cd9660_root,
                     68:        cd9660_quotactl,
                     69:        cd9660_statfs,
                     70:        cd9660_sync,
                     71:        cd9660_vget,
                     72:        cd9660_fhtovp,
                     73:        cd9660_vptofh,
                     74:        cd9660_init,
                     75:        cd9660_sysctl,
                     76:        cd9660_check_export
                     77: };
                     78:
                     79: /*
                     80:  * Called by vfs_mountroot when iso is going to be mounted as root.
                     81:  */
                     82:
                     83: static int iso_mountfs(struct vnode *devvp, struct mount *mp,
                     84:            struct proc *p, struct iso_args *argp);
                     85: int    iso_disklabelspoof(dev_t dev, void (*strat)(struct buf *),
                     86:            struct disklabel *lp);
                     87:
                     88: int
                     89: cd9660_mountroot()
                     90: {
                     91:        struct mount *mp;
                     92:        extern struct vnode *rootvp;
                     93:        struct proc *p = curproc;       /* XXX */
                     94:        int error;
                     95:        struct iso_args args;
                     96:
                     97:        /*
                     98:         * Get vnodes for swapdev and rootdev.
                     99:         */
                    100:        if ((error = bdevvp(swapdev, &swapdev_vp)) ||
                    101:            (error = bdevvp(rootdev, &rootvp))) {
                    102:                printf("cd9660_mountroot: can't setup bdevvp's");
                    103:                 return (error);
                    104:         }
                    105:
                    106:        if ((error = vfs_rootmountalloc("cd9660", "root_device", &mp)) != 0)
                    107:                return (error);
                    108:        args.flags = ISOFSMNT_ROOT;
                    109:        if ((error = iso_mountfs(rootvp, mp, p, &args)) != 0) {
                    110:                mp->mnt_vfc->vfc_refcount--;
                    111:                vfs_unbusy(mp);
                    112:                 free(mp, M_MOUNT);
                    113:                 return (error);
                    114:         }
                    115:
                    116:         CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
                    117:         (void)cd9660_statfs(mp, &mp->mnt_stat, p);
                    118:        vfs_unbusy(mp);
                    119:        inittodr(0);
                    120:
                    121:         return (0);
                    122: }
                    123:
                    124: /*
                    125:  * VFS Operations.
                    126:  *
                    127:  * mount system call
                    128:  */
                    129: int
                    130: cd9660_mount(mp, path, data, ndp, p)
                    131:        register struct mount *mp;
                    132:        const char *path;
                    133:        void *data;
                    134:        struct nameidata *ndp;
                    135:        struct proc *p;
                    136: {
                    137:        struct vnode *devvp;
                    138:        struct iso_args args;
                    139:        size_t size;
                    140:        int error;
                    141:        struct iso_mnt *imp = NULL;
                    142:
                    143:        error = copyin(data, &args, sizeof (struct iso_args));
                    144:        if (error)
                    145:                return (error);
                    146:
                    147:        if ((mp->mnt_flag & MNT_RDONLY) == 0)
                    148:                return (EROFS);
                    149:
                    150:        /*
                    151:         * If updating, check whether changing from read-only to
                    152:         * read/write; if there is no device name, that's all we do.
                    153:         */
                    154:        if (mp->mnt_flag & MNT_UPDATE) {
                    155:                imp = VFSTOISOFS(mp);
                    156:                if (args.fspec == 0)
                    157:                        return (vfs_export(mp, &imp->im_export,
                    158:                            &args.export_info));
                    159:        }
                    160:        /*
                    161:         * Not an update, or updating the name: look up the name
                    162:         * and verify that it refers to a sensible block device.
                    163:         */
                    164:        NDINIT(ndp, LOOKUP, FOLLOW, UIO_USERSPACE, args.fspec, p);
                    165:        if ((error = namei(ndp)) != 0)
                    166:                return (error);
                    167:        devvp = ndp->ni_vp;
                    168:
                    169:        if (devvp->v_type != VBLK) {
                    170:                vrele(devvp);
                    171:                return (ENOTBLK);
                    172:        }
                    173:        if (major(devvp->v_rdev) >= nblkdev) {
                    174:                vrele(devvp);
                    175:                return (ENXIO);
                    176:        }
                    177:        /*
                    178:         * If mount by non-root, then verify that user has necessary
                    179:         * permissions on the device.
                    180:         */
                    181:        if (p->p_ucred->cr_uid != 0) {
                    182:                vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY, p);
                    183:                error = VOP_ACCESS(devvp, VREAD, p->p_ucred, p);
                    184:                if (error) {
                    185:                        vput(devvp);
                    186:                        return (error);
                    187:                }
                    188:                VOP_UNLOCK(devvp, 0, p);
                    189:        }
                    190:        if ((mp->mnt_flag & MNT_UPDATE) == 0)
                    191:                error = iso_mountfs(devvp, mp, p, &args);
                    192:        else {
                    193:                if (devvp != imp->im_devvp)
                    194:                        error = EINVAL; /* needs translation */
                    195:                else
                    196:                        vrele(devvp);
                    197:        }
                    198:        if (error) {
                    199:                vrele(devvp);
                    200:                return (error);
                    201:        }
                    202:        imp = VFSTOISOFS(mp);
                    203:        (void)copyinstr(path, mp->mnt_stat.f_mntonname, MNAMELEN - 1, &size);
                    204:        bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
                    205:        (void)copyinstr(args.fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
                    206:            &size);
                    207:        bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
                    208:        bcopy(&args, &mp->mnt_stat.mount_info.iso_args, sizeof(args));
                    209:        (void)cd9660_statfs(mp, &mp->mnt_stat, p);
                    210:        return (0);
                    211: }
                    212:
                    213: /*
                    214:  * Common code for mount and mountroot
                    215:  */
                    216: static int
                    217: iso_mountfs(devvp, mp, p, argp)
                    218:        register struct vnode *devvp;
                    219:        struct mount *mp;
                    220:        struct proc *p;
                    221:        struct iso_args *argp;
                    222: {
                    223:        register struct iso_mnt *isomp = (struct iso_mnt *)0;
                    224:        struct buf *bp = NULL;
                    225:        struct buf *pribp = NULL, *supbp = NULL;
                    226:        dev_t dev = devvp->v_rdev;
                    227:        int error = EINVAL;
                    228:        int needclose = 0;
                    229:        int ronly = (mp->mnt_flag & MNT_RDONLY) != 0;
                    230:        extern struct vnode *rootvp;
                    231:        int iso_bsize;
                    232:        int iso_blknum;
                    233:        int joliet_level;
                    234:        struct iso_volume_descriptor *vdp;
                    235:        struct iso_primary_descriptor *pri = NULL;
                    236:        struct iso_supplementary_descriptor *sup = NULL;
                    237:        struct iso_directory_record *rootp;
                    238:        int logical_block_size;
                    239:        int sess;
                    240:
                    241:        if (!ronly)
                    242:                return (EROFS);
                    243:
                    244:        /*
                    245:         * Disallow multiple mounts of the same device.
                    246:         * Disallow mounting of a device that is currently in use
                    247:         * (except for root, which might share swap device for miniroot).
                    248:         * Flush out any old buffers remaining from a previous use.
                    249:         */
                    250:        if ((error = vfs_mountedon(devvp)) != 0)
                    251:                return (error);
                    252:        if (vcount(devvp) > 1 && devvp != rootvp)
                    253:                return (EBUSY);
                    254:        if ((error = vinvalbuf(devvp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
                    255:                return (error);
                    256:
                    257:        error = VOP_OPEN(devvp, ronly ? FREAD : FREAD|FWRITE, FSCRED, p);
                    258:        if (error)
                    259:                return (error);
                    260:        needclose = 1;
                    261:
                    262:        /*
                    263:         * This is the "logical sector size".  The standard says this
                    264:         * should be 2048 or the physical sector size on the device,
                    265:         * whichever is greater.  For now, we'll just use a constant.
                    266:         */
                    267:        iso_bsize = ISO_DEFAULT_BLOCK_SIZE;
                    268:
                    269:        if (argp->flags & ISOFSMNT_SESS) {
                    270:                sess = argp->sess;
                    271:                if (sess < 0)
                    272:                        sess = 0;
                    273:        } else {
                    274:                sess = 0;
                    275:                error = VOP_IOCTL(devvp, CDIOREADMSADDR, (caddr_t)&sess, 0,
                    276:                    FSCRED, p);
                    277:                if (error)
                    278:                        sess = 0;
                    279:        }
                    280:
                    281:        joliet_level = 0;
                    282:        for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
                    283:                if ((error = bread(devvp,
                    284:                    (iso_blknum + sess) * btodb(iso_bsize),
                    285:                    iso_bsize, NOCRED, &bp)) != 0)
                    286:                        goto out;
                    287:
                    288:                vdp = (struct iso_volume_descriptor *)bp->b_data;
                    289:                if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0) {
                    290:                        error = EINVAL;
                    291:                        goto out;
                    292:                }
                    293:
                    294:                switch (isonum_711 (vdp->type)){
                    295:                case ISO_VD_PRIMARY:
                    296:                        if (pribp == NULL) {
                    297:                                pribp = bp;
                    298:                                bp = NULL;
                    299:                                pri = (struct iso_primary_descriptor *)vdp;
                    300:                        }
                    301:                        break;
                    302:                case ISO_VD_SUPPLEMENTARY:
                    303:                        if (supbp == NULL) {
                    304:                                supbp = bp;
                    305:                                bp = NULL;
                    306:                                sup = (struct iso_supplementary_descriptor *)vdp;
                    307:
                    308:                                if (!(argp->flags & ISOFSMNT_NOJOLIET)) {
                    309:                                        if (bcmp(sup->escape, "%/@", 3) == 0)
                    310:                                                joliet_level = 1;
                    311:                                        if (bcmp(sup->escape, "%/C", 3) == 0)
                    312:                                                joliet_level = 2;
                    313:                                        if (bcmp(sup->escape, "%/E", 3) == 0)
                    314:                                                joliet_level = 3;
                    315:
                    316:                                        if (isonum_711 (sup->flags) & 1)
                    317:                                                joliet_level = 0;
                    318:                                }
                    319:                        }
                    320:                        break;
                    321:
                    322:                case ISO_VD_END:
                    323:                        goto vd_end;
                    324:
                    325:                default:
                    326:                        break;
                    327:                }
                    328:                if (bp) {
                    329:                        brelse(bp);
                    330:                        bp = NULL;
                    331:                }
                    332:        }
                    333:     vd_end:
                    334:        if (bp) {
                    335:                brelse(bp);
                    336:                bp = NULL;
                    337:        }
                    338:
                    339:        if (pri == NULL) {
                    340:                error = EINVAL;
                    341:                goto out;
                    342:        }
                    343:
                    344:        logical_block_size = isonum_723 (pri->logical_block_size);
                    345:
                    346:        if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE
                    347:            || (logical_block_size & (logical_block_size - 1)) != 0) {
                    348:                error = EINVAL;
                    349:                goto out;
                    350:        }
                    351:
                    352:        rootp = (struct iso_directory_record *)pri->root_directory_record;
                    353:
                    354:        isomp = malloc(sizeof *isomp, M_ISOFSMNT, M_WAITOK);
                    355:        bzero((caddr_t)isomp, sizeof *isomp);
                    356:        isomp->logical_block_size = logical_block_size;
                    357:        isomp->volume_space_size = isonum_733 (pri->volume_space_size);
                    358:        bcopy (rootp, isomp->root, sizeof isomp->root);
                    359:        isomp->root_extent = isonum_733 (rootp->extent);
                    360:        isomp->root_size = isonum_733 (rootp->size);
                    361:        isomp->joliet_level = 0;
                    362:        /*
                    363:         * Since an ISO9660 multi-session CD can also access previous sessions,
                    364:         * we have to include them into the space considerations.
                    365:         */
                    366:        isomp->volume_space_size += sess;
                    367:        isomp->im_bmask = logical_block_size - 1;
                    368:        isomp->im_bshift = ffs(logical_block_size) - 1;
                    369:
                    370:        pribp->b_flags |= B_AGE;
                    371:        brelse(pribp);
                    372:        pribp = NULL;
                    373:
                    374:        mp->mnt_data = (qaddr_t)isomp;
                    375:        mp->mnt_stat.f_fsid.val[0] = (long)dev;
                    376:        mp->mnt_stat.f_fsid.val[1] = mp->mnt_vfc->vfc_typenum;
                    377:        mp->mnt_maxsymlinklen = 0;
                    378:        mp->mnt_flag |= MNT_LOCAL;
                    379:        isomp->im_mountp = mp;
                    380:        isomp->im_dev = dev;
                    381:        isomp->im_devvp = devvp;
                    382:
                    383:        /* Check the Rock Ridge Extension support */
                    384:        if (!(argp->flags & ISOFSMNT_NORRIP)) {
                    385:                if ((error = bread(isomp->im_devvp, (isomp->root_extent +
                    386:                    isonum_711(rootp->ext_attr_length)) <<
                    387:                    (isomp->im_bshift - DEV_BSHIFT),
                    388:                    isomp->logical_block_size, NOCRED, &bp)) != 0)
                    389:                        goto out;
                    390:
                    391:                rootp = (struct iso_directory_record *)bp->b_data;
                    392:
                    393:                if ((isomp->rr_skip = cd9660_rrip_offset(rootp,isomp)) < 0) {
                    394:                    argp->flags  |= ISOFSMNT_NORRIP;
                    395:                } else {
                    396:                    argp->flags  &= ~ISOFSMNT_GENS;
                    397:                }
                    398:
                    399:                /*
                    400:                 * The contents are valid,
                    401:                 * but they will get reread as part of another vnode, so...
                    402:                 */
                    403:                bp->b_flags |= B_AGE;
                    404:                brelse(bp);
                    405:                bp = NULL;
                    406:        }
                    407:        isomp->im_flags = argp->flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS |
                    408:            ISOFSMNT_EXTATT | ISOFSMNT_NOJOLIET);
                    409:        switch (isomp->im_flags & (ISOFSMNT_NORRIP | ISOFSMNT_GENS)) {
                    410:        default:
                    411:            isomp->iso_ftype = ISO_FTYPE_DEFAULT;
                    412:            break;
                    413:        case ISOFSMNT_GENS|ISOFSMNT_NORRIP:
                    414:            isomp->iso_ftype = ISO_FTYPE_9660;
                    415:            break;
                    416:        case 0:
                    417:            isomp->iso_ftype = ISO_FTYPE_RRIP;
                    418:            break;
                    419:        }
                    420:
                    421:        /* Decide whether to use the Joliet descriptor */
                    422:
                    423:        if (isomp->iso_ftype != ISO_FTYPE_RRIP && joliet_level) {
                    424:                rootp = (struct iso_directory_record *)
                    425:                        sup->root_directory_record;
                    426:                bcopy(rootp, isomp->root, sizeof isomp->root);
                    427:                isomp->root_extent = isonum_733(rootp->extent);
                    428:                isomp->root_size = isonum_733(rootp->size);
                    429:                isomp->joliet_level = joliet_level;
                    430:                supbp->b_flags |= B_AGE;
                    431:        }
                    432:
                    433:        if (supbp) {
                    434:                brelse(supbp);
                    435:                supbp = NULL;
                    436:        }
                    437:
                    438:        devvp->v_specmountpoint = mp;
                    439:
                    440:        return (0);
                    441: out:
                    442:        if (bp)
                    443:                brelse(bp);
                    444:        if (supbp)
                    445:                brelse(supbp);
                    446:        if (needclose)
                    447:                (void)VOP_CLOSE(devvp, ronly ? FREAD : FREAD|FWRITE, NOCRED,
                    448:                    p);
                    449:        if (isomp) {
                    450:                free((caddr_t)isomp, M_ISOFSMNT);
                    451:                mp->mnt_data = (qaddr_t)0;
                    452:        }
                    453:        return (error);
                    454: }
                    455:
                    456: /*
                    457:  * Test to see if the device is an ISOFS filesystem.
                    458:  */
                    459: int
                    460: iso_disklabelspoof(dev, strat, lp)
                    461:        dev_t dev;
                    462:        void (*strat)(struct buf *);
                    463:        register struct disklabel *lp;
                    464: {
                    465:        struct buf *bp = NULL;
                    466:        struct iso_volume_descriptor *vdp;
                    467:        struct iso_primary_descriptor *pri;
                    468:        int logical_block_size;
                    469:        int error = EINVAL;
                    470:        int iso_blknum;
                    471:        int i;
                    472:
                    473:        bp = geteblk(ISO_DEFAULT_BLOCK_SIZE);
                    474:        bp->b_dev = dev;
                    475:
                    476:        for (iso_blknum = 16; iso_blknum < 100; iso_blknum++) {
                    477:                bp->b_blkno = iso_blknum * btodb(ISO_DEFAULT_BLOCK_SIZE);
                    478:                bp->b_bcount = ISO_DEFAULT_BLOCK_SIZE;
                    479:                bp->b_flags = B_BUSY | B_READ;
                    480:                bp->b_cylinder = bp->b_blkno / lp->d_secpercyl;
                    481:
                    482:                /*printf("d_secsize %d iso_blknum %d b_blkno %d bcount %d\n",
                    483:                    lp->d_secsize, iso_blknum, bp->b_blkno, bp->b_bcount);*/
                    484:
                    485:                (*strat)(bp);
                    486:
                    487:                if (biowait(bp))
                    488:                        goto out;
                    489:
                    490:                vdp = (struct iso_volume_descriptor *)bp->b_data;
                    491:                /*printf("%2x%2x%2x type %2x\n", vdp->id[0], vdp->id[1],
                    492:                    vdp->id[2], isonum_711(vdp->type));*/
                    493:                if (bcmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) != 0 ||
                    494:                    isonum_711 (vdp->type) == ISO_VD_END)
                    495:                        goto out;
                    496:
                    497:                if (isonum_711 (vdp->type) == ISO_VD_PRIMARY)
                    498:                        break;
                    499:        }
                    500:
                    501:        if (isonum_711 (vdp->type) != ISO_VD_PRIMARY)
                    502:                goto out;
                    503:
                    504:        pri = (struct iso_primary_descriptor *)vdp;
                    505:        logical_block_size = isonum_723 (pri->logical_block_size);
                    506:        if (logical_block_size < DEV_BSIZE || logical_block_size > MAXBSIZE ||
                    507:            (logical_block_size & (logical_block_size - 1)) != 0)
                    508:                goto out;
                    509:
                    510:        /*
                    511:         * build a disklabel for the CD
                    512:         */
                    513:        strncpy(lp->d_typename, pri->volume_id, sizeof lp->d_typename);
                    514:        strncpy(lp->d_packname, pri->volume_id+16, sizeof lp->d_packname);
                    515:        for (i = 0; i < MAXPARTITIONS; i++) {
                    516:                DL_SETPSIZE(&lp->d_partitions[i], 0);
                    517:                DL_SETPOFFSET(&lp->d_partitions[i], 0);
                    518:        }
                    519:        DL_SETPOFFSET(&lp->d_partitions[0], 0);
                    520:        DL_SETPSIZE(&lp->d_partitions[0], DL_GETDSIZE(lp));
                    521:        lp->d_partitions[0].p_fstype = FS_ISO9660;
                    522:        DL_SETPOFFSET(&lp->d_partitions[RAW_PART], 0);
                    523:        DL_SETPSIZE(&lp->d_partitions[RAW_PART], DL_GETDSIZE(lp));
                    524:        lp->d_partitions[RAW_PART].p_fstype = FS_ISO9660;
                    525:        lp->d_npartitions = RAW_PART + 1;
                    526:        lp->d_bbsize = 8192;            /* fake */
                    527:        lp->d_sbsize = 64*1024;         /* fake */
                    528:        lp->d_version = 1;
                    529:
                    530:        lp->d_magic = DISKMAGIC;
                    531:        lp->d_magic2 = DISKMAGIC;
                    532:        lp->d_checksum = dkcksum(lp);
                    533:        error = 0;
                    534: out:
                    535:        bp->b_flags |= B_INVAL;
                    536:        brelse(bp);
                    537:        return (error);
                    538: }
                    539:
                    540: /*
                    541:  * Make a filesystem operational.
                    542:  * Nothing to do at the moment.
                    543:  */
                    544: /* ARGSUSED */
                    545: int
                    546: cd9660_start(mp, flags, p)
                    547:        struct mount *mp;
                    548:        int flags;
                    549:        struct proc *p;
                    550: {
                    551:        return (0);
                    552: }
                    553:
                    554: /*
                    555:  * unmount system call
                    556:  */
                    557: int
                    558: cd9660_unmount(mp, mntflags, p)
                    559:        struct mount *mp;
                    560:        int mntflags;
                    561:        struct proc *p;
                    562: {
                    563:        register struct iso_mnt *isomp;
                    564:        int error, flags = 0;
                    565:
                    566:        if (mntflags & MNT_FORCE)
                    567:                flags |= FORCECLOSE;
                    568: #if 0
                    569:        mntflushbuf(mp, 0);
                    570:        if (mntinvalbuf(mp))
                    571:                return (EBUSY);
                    572: #endif
                    573:        if ((error = vflush(mp, NULLVP, flags)) != 0)
                    574:                return (error);
                    575:
                    576:        isomp = VFSTOISOFS(mp);
                    577:
                    578: #ifdef ISODEVMAP
                    579:        if (isomp->iso_ftype == ISO_FTYPE_RRIP)
                    580:                iso_dunmap(isomp->im_dev);
                    581: #endif
                    582:
                    583:        isomp->im_devvp->v_specmountpoint = NULL;
                    584:        error = VOP_CLOSE(isomp->im_devvp, FREAD, NOCRED, p);
                    585:        vrele(isomp->im_devvp);
                    586:        free((caddr_t)isomp, M_ISOFSMNT);
                    587:        mp->mnt_data = (qaddr_t)0;
                    588:        mp->mnt_flag &= ~MNT_LOCAL;
                    589:        return (error);
                    590: }
                    591:
                    592: /*
                    593:  * Return root of a filesystem
                    594:  */
                    595: int
                    596: cd9660_root(mp, vpp)
                    597:        struct mount *mp;
                    598:        struct vnode **vpp;
                    599: {
                    600:        struct iso_mnt *imp = VFSTOISOFS(mp);
                    601:        struct iso_directory_record *dp =
                    602:            (struct iso_directory_record *)imp->root;
                    603:        ino_t ino = isodirino(dp, imp);
                    604:
                    605:        /*
                    606:         * With RRIP we must use the `.' entry of the root directory.
                    607:         * Simply tell vget, that it's a relocated directory.
                    608:         */
                    609:        return (cd9660_vget_internal(mp, ino, vpp,
                    610:            imp->iso_ftype == ISO_FTYPE_RRIP, dp));
                    611: }
                    612:
                    613: /*
                    614:  * Do operations associated with quotas, not supported
                    615:  */
                    616: /* ARGSUSED */
                    617: int
                    618: cd9660_quotactl(mp, cmd, uid, arg, p)
                    619:        struct mount *mp;
                    620:        int cmd;
                    621:        uid_t uid;
                    622:        caddr_t arg;
                    623:        struct proc *p;
                    624: {
                    625:
                    626:        return (EOPNOTSUPP);
                    627: }
                    628:
                    629: /*
                    630:  * Get file system statistics.
                    631:  */
                    632: int
                    633: cd9660_statfs(mp, sbp, p)
                    634:        struct mount *mp;
                    635:        register struct statfs *sbp;
                    636:        struct proc *p;
                    637: {
                    638:        register struct iso_mnt *isomp;
                    639:
                    640:        isomp = VFSTOISOFS(mp);
                    641:
                    642:        sbp->f_bsize = isomp->logical_block_size;
                    643:        sbp->f_iosize = sbp->f_bsize;   /* XXX */
                    644:        sbp->f_blocks = isomp->volume_space_size;
                    645:        sbp->f_bfree = 0; /* total free blocks */
                    646:        sbp->f_bavail = 0; /* blocks free for non superuser */
                    647:        sbp->f_files =  0; /* total files */
                    648:        sbp->f_ffree = 0; /* free file nodes */
                    649:        if (sbp != &mp->mnt_stat) {
                    650:                bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN);
                    651:                bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname,
                    652:                    MNAMELEN);
                    653:                bcopy(&mp->mnt_stat.mount_info.iso_args,
                    654:                    &sbp->mount_info.iso_args, sizeof(struct iso_args));
                    655:        }
                    656:        /* Use the first spare for flags: */
                    657:        sbp->f_spare[0] = isomp->im_flags;
                    658:        return (0);
                    659: }
                    660:
                    661: /* ARGSUSED */
                    662: int
                    663: cd9660_sync(mp, waitfor, cred, p)
                    664:        struct mount *mp;
                    665:        int waitfor;
                    666:        struct ucred *cred;
                    667:        struct proc *p;
                    668: {
                    669:        return (0);
                    670: }
                    671:
                    672: /*
                    673:  * File handle to vnode
                    674:  *
                    675:  * Have to be really careful about stale file handles:
                    676:  * - check that the inode number is in range
                    677:  * - call iget() to get the locked inode
                    678:  * - check for an unallocated inode (i_mode == 0)
                    679:  * - check that the generation number matches
                    680:  */
                    681:
                    682: struct ifid {
                    683:        ushort  ifid_len;
                    684:        ushort  ifid_pad;
                    685:        int     ifid_ino;
                    686:        long    ifid_start;
                    687: };
                    688:
                    689: /* ARGSUSED */
                    690: int
                    691: cd9660_fhtovp(mp, fhp, vpp)
                    692:        register struct mount *mp;
                    693:        struct fid *fhp;
                    694:        struct vnode **vpp;
                    695: {
                    696:        struct ifid *ifhp = (struct ifid *)fhp;
                    697:        register struct iso_node *ip;
                    698:        struct vnode *nvp;
                    699:        int error;
                    700:
                    701: #ifdef ISOFS_DBG
                    702:        printf("fhtovp: ino %d, start %ld\n", ifhp->ifid_ino,
                    703:            ifhp->ifid_start);
                    704: #endif
                    705:
                    706:        if ((error = VFS_VGET(mp, ifhp->ifid_ino, &nvp)) != 0) {
                    707:                *vpp = NULLVP;
                    708:                return (error);
                    709:        }
                    710:        ip = VTOI(nvp);
                    711:        if (ip->inode.iso_mode == 0) {
                    712:                vput(nvp);
                    713:                *vpp = NULLVP;
                    714:                return (ESTALE);
                    715:        }
                    716:        *vpp = nvp;
                    717:        return (0);
                    718: }
                    719:
                    720: int
                    721: cd9660_vget(mp, ino, vpp)
                    722:        struct mount *mp;
                    723:        ino_t ino;
                    724:        struct vnode **vpp;
                    725: {
                    726:
                    727:        /*
                    728:         * XXXX
                    729:         * It would be nice if we didn't always set the `relocated' flag
                    730:         * and force the extra read, but I don't want to think about fixing
                    731:         * that right now.
                    732:         */
                    733:        return (cd9660_vget_internal(mp, ino, vpp,
                    734: #if 0
                    735:            VFSTOISOFS(mp)->iso_ftype == ISO_FTYPE_RRIP,
                    736: #else
                    737:            0,
                    738: #endif
                    739:            NULL));
                    740: }
                    741:
                    742: int
                    743: cd9660_vget_internal(mp, ino, vpp, relocated, isodir)
                    744:        struct mount *mp;
                    745:        ino_t ino;
                    746:        struct vnode **vpp;
                    747:        int relocated;
                    748:        struct iso_directory_record *isodir;
                    749: {
                    750:        register struct iso_mnt *imp;
                    751:        struct iso_node *ip;
                    752:        struct buf *bp;
                    753:        struct vnode *vp, *nvp;
                    754:        dev_t dev;
                    755:        int error;
                    756:
                    757: retry:
                    758:        imp = VFSTOISOFS(mp);
                    759:        dev = imp->im_dev;
                    760:        if ((*vpp = cd9660_ihashget(dev, ino)) != NULLVP)
                    761:                return (0);
                    762:
                    763:        /* Allocate a new vnode/iso_node. */
                    764:        if ((error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, &vp)) != 0) {
                    765:                *vpp = NULLVP;
                    766:                return (error);
                    767:        }
                    768:        MALLOC(ip, struct iso_node *, sizeof(struct iso_node), M_ISOFSNODE,
                    769:            M_WAITOK);
                    770:        bzero((caddr_t)ip, sizeof(struct iso_node));
                    771:        lockinit(&ip->i_lock, PINOD, "isoinode", 0, 0);
                    772:        vp->v_data = ip;
                    773:        ip->i_vnode = vp;
                    774:        ip->i_dev = dev;
                    775:        ip->i_number = ino;
                    776:
                    777:        /*
                    778:         * Put it onto its hash chain and lock it so that other requests for
                    779:         * this inode will block if they arrive while we are sleeping waiting
                    780:         * for old data structures to be purged or for the contents of the
                    781:         * disk portion of this inode to be read.
                    782:         */
                    783:        error = cd9660_ihashins(ip);
                    784:
                    785:        if (error) {
                    786:                vrele(vp);
                    787:
                    788:                if (error == EEXIST)
                    789:                        goto retry;
                    790:
                    791:                return (error);
                    792:        }
                    793:
                    794:        if (isodir == 0) {
                    795:                int lbn, off;
                    796:
                    797:                lbn = lblkno(imp, ino);
                    798:                if (lbn >= imp->volume_space_size) {
                    799:                        vput(vp);
                    800:                        printf("fhtovp: lbn exceed volume space %d\n", lbn);
                    801:                        return (ESTALE);
                    802:                }
                    803:
                    804:                off = blkoff(imp, ino);
                    805:                if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size)
                    806:                    {
                    807:                        vput(vp);
                    808:                        printf("fhtovp: crosses block boundary %d\n",
                    809:                            off + ISO_DIRECTORY_RECORD_SIZE);
                    810:                        return (ESTALE);
                    811:                }
                    812:
                    813:                error = bread(imp->im_devvp,
                    814:                              lbn << (imp->im_bshift - DEV_BSHIFT),
                    815:                              imp->logical_block_size, NOCRED, &bp);
                    816:                if (error) {
                    817:                        vput(vp);
                    818:                        brelse(bp);
                    819:                        printf("fhtovp: bread error %d\n",error);
                    820:                        return (error);
                    821:                }
                    822:                isodir = (struct iso_directory_record *)(bp->b_data + off);
                    823:
                    824:                if (off + isonum_711(isodir->length) >
                    825:                    imp->logical_block_size) {
                    826:                        vput(vp);
                    827:                        if (bp != 0)
                    828:                                brelse(bp);
                    829:                        printf("fhtovp: directory crosses block boundary %d[off=%d/len=%d]\n",
                    830:                            off +isonum_711(isodir->length), off,
                    831:                            isonum_711(isodir->length));
                    832:                        return (ESTALE);
                    833:                }
                    834:
                    835: #if 0
                    836:                if (isonum_733(isodir->extent) +
                    837:                    isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) {
                    838:                        if (bp != 0)
                    839:                                brelse(bp);
                    840:                        printf("fhtovp: file start miss %d vs %d\n",
                    841:                            isonum_733(isodir->extent) +
                    842:                            isonum_711(isodir->ext_attr_length),
                    843:                            ifhp->ifid_start);
                    844:                        return (ESTALE);
                    845:                }
                    846: #endif
                    847:        } else
                    848:                bp = 0;
                    849:
                    850:        ip->i_mnt = imp;
                    851:        ip->i_devvp = imp->im_devvp;
                    852:        VREF(ip->i_devvp);
                    853:
                    854:        if (relocated) {
                    855:                /*
                    856:                 * On relocated directories we must
                    857:                 * read the `.' entry out of a dir.
                    858:                 */
                    859:                ip->iso_start = ino >> imp->im_bshift;
                    860:                if (bp != 0)
                    861:                        brelse(bp);
                    862:                if ((error = cd9660_bufatoff(ip, (off_t)0, NULL, &bp)) != 0) {
                    863:                        vput(vp);
                    864:                        return (error);
                    865:                }
                    866:                isodir = (struct iso_directory_record *)bp->b_data;
                    867:        }
                    868:
                    869:        ip->iso_extent = isonum_733(isodir->extent);
                    870:        ip->i_size = (u_int32_t) isonum_733(isodir->size);
                    871:        ip->iso_start = isonum_711(isodir->ext_attr_length) + ip->iso_extent;
                    872:
                    873:        /*
                    874:         * Setup time stamp, attribute
                    875:         */
                    876:        vp->v_type = VNON;
                    877:        switch (imp->iso_ftype) {
                    878:        default:        /* ISO_FTYPE_9660 */
                    879:            {
                    880:                struct buf *bp2;
                    881:                int off;
                    882:                if ((imp->im_flags & ISOFSMNT_EXTATT) &&
                    883:                    (off = isonum_711(isodir->ext_attr_length)))
                    884:                        cd9660_bufatoff(ip, (off_t)-(off << imp->im_bshift),
                    885:                            NULL, &bp2);
                    886:                else
                    887:                        bp2 = NULL;
                    888:                cd9660_defattr(isodir, ip, bp2);
                    889:                cd9660_deftstamp(isodir, ip, bp2);
                    890:                if (bp2)
                    891:                        brelse(bp2);
                    892:                break;
                    893:            }
                    894:        case ISO_FTYPE_RRIP:
                    895:                cd9660_rrip_analyze(isodir, ip, imp);
                    896:                break;
                    897:        }
                    898:
                    899:        if (bp != 0)
                    900:                brelse(bp);
                    901:
                    902:        /*
                    903:         * Initialize the associated vnode
                    904:         */
                    905:        switch (vp->v_type = IFTOVT(ip->inode.iso_mode)) {
                    906:        case VFIFO:
                    907: #ifdef FIFO
                    908:                vp->v_op = cd9660_fifoop_p;
                    909:                break;
                    910: #else
                    911:                vput(vp);
                    912:                return (EOPNOTSUPP);
                    913: #endif /* FIFO */
                    914:        case VCHR:
                    915:        case VBLK:
                    916:                /*
                    917:                 * if device, look at device number table for translation
                    918:                 */
                    919: #ifdef ISODEVMAP
                    920:                if (dp = iso_dmap(dev, ino, 0))
                    921:                        ip->inode.iso_rdev = dp->d_dev;
                    922: #endif
                    923:                vp->v_op = cd9660_specop_p;
                    924:                if ((nvp = checkalias(vp, ip->inode.iso_rdev, mp)) != NULL) {
                    925:                        /*
                    926:                         * Discard unneeded vnode, but save its iso_node.
                    927:                         * Note that the lock is carried over in the iso_node
                    928:                         */
                    929:                        nvp->v_data = vp->v_data;
                    930:                        vp->v_data = NULL;
                    931:                        vp->v_op = spec_vnodeop_p;
                    932:                        vrele(vp);
                    933:                        vgone(vp);
                    934:                        /*
                    935:                         * Reinitialize aliased inode.
                    936:                         */
                    937:                        vp = nvp;
                    938:                        ip->i_vnode = vp;
                    939:                }
                    940:                break;
                    941:        case VLNK:
                    942:        case VNON:
                    943:        case VSOCK:
                    944:        case VDIR:
                    945:        case VBAD:
                    946:                break;
                    947:        case VREG:
                    948:                uvm_vnp_setsize(vp, ip->i_size);
                    949:                break;
                    950:        }
                    951:
                    952:        if (ip->iso_extent == imp->root_extent)
                    953:                vp->v_flag |= VROOT;
                    954:
                    955:        /*
                    956:         * XXX need generation number?
                    957:         */
                    958:
                    959:        *vpp = vp;
                    960:        return (0);
                    961: }
                    962:
                    963: /*
                    964:  * Vnode pointer to File handle
                    965:  */
                    966: /* ARGSUSED */
                    967: int
                    968: cd9660_vptofh(vp, fhp)
                    969:        struct vnode *vp;
                    970:        struct fid *fhp;
                    971: {
                    972:        register struct iso_node *ip = VTOI(vp);
                    973:        register struct ifid *ifhp;
                    974:
                    975:        ifhp = (struct ifid *)fhp;
                    976:        ifhp->ifid_len = sizeof(struct ifid);
                    977:
                    978:        ifhp->ifid_ino = ip->i_number;
                    979:        ifhp->ifid_start = ip->iso_start;
                    980:
                    981: #ifdef ISOFS_DBG
                    982:        printf("vptofh: ino %d, start %ld\n",
                    983:            ifhp->ifid_ino,ifhp->ifid_start);
                    984: #endif
                    985:        return (0);
                    986: }
                    987:
                    988: /*
                    989:  * Verify a remote client has export rights and return these rights via
                    990:  * exflagsp and credanonp.
                    991:  */
                    992: int
                    993: cd9660_check_export(mp, nam, exflagsp, credanonp)
                    994:        register struct mount *mp;
                    995:        struct mbuf *nam;
                    996:        int *exflagsp;
                    997:        struct ucred **credanonp;
                    998: {
                    999:        register struct netcred *np;
                   1000:        register struct iso_mnt *imp = VFSTOISOFS(mp);
                   1001:
                   1002:        /*
                   1003:         * Get the export permission structure for this <mp, client> tuple.
                   1004:         */
                   1005:        np = vfs_export_lookup(mp, &imp->im_export, nam);
                   1006:        if (np == NULL)
                   1007:                return (EACCES);
                   1008:
                   1009:        *exflagsp = np->netc_exflags;
                   1010:        *credanonp = &np->netc_anon;
                   1011:        return (0);
                   1012: }

CVSweb