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