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