Annotation of sys/isofs/cd9660/cd9660_vfsops.c, Revision 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