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_vnops.c 8.9 (Berkeley) 07/24/94 13 */ 14 15 #include <sys/param.h> 16 #include <sys/systm.h> 17 #include <sys/namei.h> 18 #include <sys/resourcevar.h> 19 #include <sys/kernel.h> 20 #include <sys/file.h> 21 #include <sys/stat.h> 22 #include <sys/buf.h> 23 #include <sys/proc.h> 24 #include <sys/conf.h> 25 #include <sys/mount.h> 26 #include <sys/vnode.h> 27 #include <miscfs/specfs/specdev.h> 28 #include <miscfs/fifofs/fifo.h> 29 #include <sys/malloc.h> 30 #include <sys/dir.h> 31 32 #include <isofs/cd9660/iso.h> 33 #include <isofs/cd9660/cd9660_node.h> 34 #include <isofs/cd9660/iso_rrip.h> 35 36 #if 0 37 /* 38 * Mknod vnode call 39 * Actually remap the device number 40 */ 41 cd9660_mknod(ndp, vap, cred, p) 42 struct nameidata *ndp; 43 struct ucred *cred; 44 struct vattr *vap; 45 struct proc *p; 46 { 47 #ifndef ISODEVMAP 48 free(ndp->ni_pnbuf, M_NAMEI); 49 vput(ndp->ni_dvp); 50 vput(ndp->ni_vp); 51 return (EINVAL); 52 #else 53 register struct vnode *vp; 54 struct iso_node *ip; 55 struct iso_dnode *dp; 56 int error; 57 58 vp = ndp->ni_vp; 59 ip = VTOI(vp); 60 61 if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP 62 || vap->va_type != vp->v_type 63 || (vap->va_type != VCHR && vap->va_type != VBLK)) { 64 free(ndp->ni_pnbuf, M_NAMEI); 65 vput(ndp->ni_dvp); 66 vput(ndp->ni_vp); 67 return (EINVAL); 68 } 69 70 dp = iso_dmap(ip->i_dev,ip->i_number,1); 71 if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) { 72 /* same as the unmapped one, delete the mapping */ 73 remque(dp); 74 FREE(dp,M_CACHE); 75 } else 76 /* enter new mapping */ 77 dp->d_dev = vap->va_rdev; 78 79 /* 80 * Remove inode so that it will be reloaded by iget and 81 * checked to see if it is an alias of an existing entry 82 * in the inode cache. 83 */ 84 vput(vp); 85 vp->v_type = VNON; 86 vgone(vp); 87 return (0); 88 #endif 89 } 90 #endif 91 92 /* 93 * Open called. 94 * 95 * Nothing to do. 96 */ 97 /* ARGSUSED */ 98 int 99 cd9660_open(ap) 100 struct vop_open_args /* { 101 struct vnode *a_vp; 102 int a_mode; 103 struct ucred *a_cred; 104 struct proc *a_p; 105 } */ *ap; 106 { 107 return (0); 108 } 109 110 /* 111 * Close called 112 * 113 * Update the times on the inode on writeable file systems. 114 */ 115 /* ARGSUSED */ 116 int 117 cd9660_close(ap) 118 struct vop_close_args /* { 119 struct vnode *a_vp; 120 int a_fflag; 121 struct ucred *a_cred; 122 struct proc *a_p; 123 } */ *ap; 124 { 125 return (0); 126 } 127 128 /* 129 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 130 * The mode is shifted to select the owner/group/other fields. The 131 * super user is granted all permissions. 132 */ 133 /* ARGSUSED */ 134 cd9660_access(ap) 135 struct vop_access_args /* { 136 struct vnode *a_vp; 137 int a_mode; 138 struct ucred *a_cred; 139 struct proc *a_p; 140 } */ *ap; 141 { 142 struct iso_node *ip = VTOI(ap->a_vp); 143 struct ucred *cred = ap->a_cred; 144 mode_t mask, mode = ap->a_mode; 145 gid_t *gp; 146 int i, error; 147 148 /* User id 0 always gets access. */ 149 if (cred->cr_uid == 0) 150 return (0); 151 152 mask = 0; 153 154 /* Otherwise, check the owner. */ 155 if (cred->cr_uid == ip->inode.iso_uid) { 156 if (mode & VEXEC) 157 mask |= S_IXUSR; 158 if (mode & VREAD) 159 mask |= S_IRUSR; 160 if (mode & VWRITE) 161 mask |= S_IWUSR; 162 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); 163 } 164 165 /* Otherwise, check the groups. */ 166 for (i = 0, gp = cred->cr_groups; i < cred->cr_ngroups; i++, gp++) 167 if (ip->inode.iso_gid == *gp) { 168 if (mode & VEXEC) 169 mask |= S_IXGRP; 170 if (mode & VREAD) 171 mask |= S_IRGRP; 172 if (mode & VWRITE) 173 mask |= S_IWGRP; 174 return ((ip->inode.iso_mode & mask) == mask ? 175 0 : EACCES); 176 } 177 178 /* Otherwise, check everyone else. */ 179 if (mode & VEXEC) 180 mask |= S_IXOTH; 181 if (mode & VREAD) 182 mask |= S_IROTH; 183 if (mode & VWRITE) 184 mask |= S_IWOTH; 185 return ((ip->inode.iso_mode & mask) == mask ? 0 : EACCES); 186 } 187 188 cd9660_getattr(ap) 189 struct vop_getattr_args /* { 190 struct vnode *a_vp; 191 struct vattr *a_vap; 192 struct ucred *a_cred; 193 struct proc *a_p; 194 } */ *ap; 195 196 { 197 struct vnode *vp = ap->a_vp; 198 register struct vattr *vap = ap->a_vap; 199 register struct iso_node *ip = VTOI(vp); 200 int i; 201 202 vap->va_fsid = ip->i_dev; 203 vap->va_fileid = ip->i_number; 204 205 vap->va_mode = ip->inode.iso_mode; 206 vap->va_nlink = ip->inode.iso_links; 207 vap->va_uid = ip->inode.iso_uid; 208 vap->va_gid = ip->inode.iso_gid; 209 vap->va_atime = ip->inode.iso_atime; 210 vap->va_mtime = ip->inode.iso_mtime; 211 vap->va_ctime = ip->inode.iso_ctime; 212 vap->va_rdev = ip->inode.iso_rdev; 213 214 vap->va_size = (u_quad_t) ip->i_size; 215 vap->va_flags = 0; 216 vap->va_gen = 1; 217 vap->va_blocksize = ip->i_mnt->logical_block_size; 218 vap->va_bytes = (u_quad_t) ip->i_size; 219 vap->va_type = vp->v_type; 220 return (0); 221 } 222 223 #if ISO_DEFAULT_BLOCK_SIZE >= NBPG 224 #ifdef DEBUG 225 extern int doclusterread; 226 #else 227 #define doclusterread 1 228 #endif 229 #else 230 /* XXX until cluster routines can handle block sizes less than one page */ 231 #define doclusterread 0 232 #endif 233 234 /* 235 * Vnode op for reading. 236 */ 237 cd9660_read(ap) 238 struct vop_read_args /* { 239 struct vnode *a_vp; 240 struct uio *a_uio; 241 int a_ioflag; 242 struct ucred *a_cred; 243 } */ *ap; 244 { 245 struct vnode *vp = ap->a_vp; 246 register struct uio *uio = ap->a_uio; 247 register struct iso_node *ip = VTOI(vp); 248 register struct iso_mnt *imp; 249 struct buf *bp; 250 daddr_t lbn, bn, rablock; 251 off_t diff; 252 int rasize, error = 0; 253 long size, n, on; 254 255 if (uio->uio_resid == 0) 256 return (0); 257 if (uio->uio_offset < 0) 258 return (EINVAL); 259 ip->i_flag |= IN_ACCESS; 260 imp = ip->i_mnt; 261 do { 262 lbn = iso_lblkno(imp, uio->uio_offset); 263 on = iso_blkoff(imp, uio->uio_offset); 264 n = min((unsigned)(imp->logical_block_size - on), 265 uio->uio_resid); 266 diff = (off_t)ip->i_size - uio->uio_offset; 267 if (diff <= 0) 268 return (0); 269 if (diff < n) 270 n = diff; 271 size = iso_blksize(imp, ip, lbn); 272 rablock = lbn + 1; 273 if (doclusterread) { 274 if (iso_lblktosize(imp, rablock) <= ip->i_size) 275 error = cluster_read(vp, (off_t)ip->i_size, 276 lbn, size, NOCRED, &bp); 277 else 278 error = bread(vp, lbn, size, NOCRED, &bp); 279 } else { 280 if (vp->v_lastr + 1 == lbn && 281 iso_lblktosize(imp, rablock) < ip->i_size) { 282 rasize = iso_blksize(imp, ip, rablock); 283 error = breadn(vp, lbn, size, &rablock, 284 &rasize, 1, NOCRED, &bp); 285 } else 286 error = bread(vp, lbn, size, NOCRED, &bp); 287 } 288 vp->v_lastr = lbn; 289 n = min(n, size - bp->b_resid); 290 if (error) { 291 brelse(bp); 292 return (error); 293 } 294 295 error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 296 if (n + on == imp->logical_block_size || 297 uio->uio_offset == (off_t)ip->i_size) 298 bp->b_flags |= B_AGE; 299 brelse(bp); 300 } while (error == 0 && uio->uio_resid > 0 && n != 0); 301 return (error); 302 } 303 304 /* ARGSUSED */ 305 int 306 cd9660_ioctl(ap) 307 struct vop_ioctl_args /* { 308 struct vnode *a_vp; 309 int a_command; 310 caddr_t a_data; 311 int a_fflag; 312 struct ucred *a_cred; 313 struct proc *a_p; 314 } */ *ap; 315 { 316 printf("You did ioctl for isofs !!\n"); 317 return (ENOTTY); 318 } 319 320 /* ARGSUSED */ 321 int 322 cd9660_select(ap) 323 struct vop_select_args /* { 324 struct vnode *a_vp; 325 int a_which; 326 int a_fflags; 327 struct ucred *a_cred; 328 struct proc *a_p; 329 } */ *ap; 330 { 331 332 /* 333 * We should really check to see if I/O is possible. 334 */ 335 return (1); 336 } 337 338 /* 339 * Mmap a file 340 * 341 * NB Currently unsupported. 342 */ 343 /* ARGSUSED */ 344 int 345 cd9660_mmap(ap) 346 struct vop_mmap_args /* { 347 struct vnode *a_vp; 348 int a_fflags; 349 struct ucred *a_cred; 350 struct proc *a_p; 351 } */ *ap; 352 { 353 354 return (EINVAL); 355 } 356 357 /* 358 * Seek on a file 359 * 360 * Nothing to do, so just return. 361 */ 362 /* ARGSUSED */ 363 int 364 cd9660_seek(ap) 365 struct vop_seek_args /* { 366 struct vnode *a_vp; 367 off_t a_oldoff; 368 off_t a_newoff; 369 struct ucred *a_cred; 370 } */ *ap; 371 { 372 373 return (0); 374 } 375 376 /* 377 * Structure for reading directories 378 */ 379 struct isoreaddir { 380 struct dirent saveent; 381 struct dirent assocent; 382 struct dirent current; 383 off_t saveoff; 384 off_t assocoff; 385 off_t curroff; 386 struct uio *uio; 387 off_t uio_off; 388 int eofflag; 389 u_long *cookies; 390 int ncookies; 391 }; 392 393 static int 394 iso_uiodir(idp,dp,off) 395 struct isoreaddir *idp; 396 struct dirent *dp; 397 off_t off; 398 { 399 int error; 400 401 dp->d_name[dp->d_namlen] = 0; 402 dp->d_reclen = DIRSIZ(dp); 403 404 if (idp->uio->uio_resid < dp->d_reclen) { 405 idp->eofflag = 0; 406 return (-1); 407 } 408 409 if (idp->cookies) { 410 if (idp->ncookies <= 0) { 411 idp->eofflag = 0; 412 return (-1); 413 } 414 415 *idp->cookies++ = off; 416 --idp->ncookies; 417 } 418 419 if (error = uiomove(dp,dp->d_reclen,idp->uio)) 420 return (error); 421 idp->uio_off = off; 422 return (0); 423 } 424 425 static int 426 iso_shipdir(idp) 427 struct isoreaddir *idp; 428 { 429 struct dirent *dp; 430 int cl, sl, assoc; 431 int error; 432 char *cname, *sname; 433 434 cl = idp->current.d_namlen; 435 cname = idp->current.d_name; 436 if (assoc = cl > 1 && *cname == ASSOCCHAR) { 437 cl--; 438 cname++; 439 } 440 441 dp = &idp->saveent; 442 sname = dp->d_name; 443 if (!(sl = dp->d_namlen)) { 444 dp = &idp->assocent; 445 sname = dp->d_name + 1; 446 sl = dp->d_namlen - 1; 447 } 448 if (sl > 0) { 449 if (sl != cl 450 || bcmp(sname,cname,sl)) { 451 if (idp->assocent.d_namlen) { 452 if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) 453 return (error); 454 idp->assocent.d_namlen = 0; 455 } 456 if (idp->saveent.d_namlen) { 457 if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) 458 return (error); 459 idp->saveent.d_namlen = 0; 460 } 461 } 462 } 463 idp->current.d_reclen = DIRSIZ(&idp->current); 464 if (assoc) { 465 idp->assocoff = idp->curroff; 466 bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 467 } else { 468 idp->saveoff = idp->curroff; 469 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 470 } 471 return (0); 472 } 473 474 /* 475 * Vnode op for readdir 476 */ 477 int 478 cd9660_readdir(ap) 479 struct vop_readdir_args /* { 480 struct vnode *a_vp; 481 struct uio *a_uio; 482 struct ucred *a_cred; 483 int *a_eofflag; 484 u_long *a_cookies; 485 int a_ncookies; 486 } */ *ap; 487 { 488 register struct uio *uio = ap->a_uio; 489 struct isoreaddir *idp; 490 int entryoffsetinblock; 491 int error = 0; 492 int endsearch; 493 struct iso_directory_record *ep; 494 u_short elen; 495 int reclen; 496 struct iso_mnt *imp; 497 struct iso_node *ip; 498 struct buf *bp = NULL; 499 500 ip = VTOI(ap->a_vp); 501 imp = ip->i_mnt; 502 503 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 504 idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 505 /* 506 * XXX 507 * Is it worth trying to figure out the type? 508 */ 509 idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 510 DT_UNKNOWN; 511 idp->uio = uio; 512 idp->eofflag = 1; 513 idp->cookies = ap->a_cookies; 514 idp->ncookies = ap->a_ncookies; 515 idp->curroff = uio->uio_offset; 516 517 entryoffsetinblock = iso_blkoff(imp, idp->curroff); 518 if (entryoffsetinblock != 0) { 519 if (error = iso_blkatoff(ip, idp->curroff, &bp)) { 520 FREE(idp,M_TEMP); 521 return (error); 522 } 523 } 524 525 endsearch = roundup(ip->i_size, imp->logical_block_size); 526 527 while (idp->curroff < endsearch) { 528 /* 529 * If offset is on a block boundary, 530 * read the next directory block. 531 * Release previous if it exists. 532 */ 533 534 if (iso_blkoff(imp, idp->curroff) == 0) { 535 if (bp != NULL) 536 brelse(bp); 537 if (error = iso_blkatoff(ip, idp->curroff, &bp)) 538 break; 539 entryoffsetinblock = 0; 540 } 541 /* 542 * Get pointer to next entry. 543 */ 544 545 ep = (struct iso_directory_record *) 546 (bp->b_un.b_addr + entryoffsetinblock); 547 548 reclen = isonum_711 (ep->length); 549 if (reclen == 0) { 550 /* skip to next block, if any */ 551 idp->curroff = 552 roundup(idp->curroff, imp->logical_block_size); 553 continue; 554 } 555 556 if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 557 error = EINVAL; 558 /* illegal entry, stop */ 559 break; 560 } 561 562 if (entryoffsetinblock + reclen > imp->logical_block_size) { 563 error = EINVAL; 564 /* illegal directory, so stop looking */ 565 break; 566 } 567 568 idp->current.d_namlen = isonum_711(ep->name_len); 569 570 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 571 error = EINVAL; 572 /* illegal entry, stop */ 573 break; 574 } 575 576 if (isonum_711(ep->flags)&2) 577 isodirino(&idp->current.d_fileno,ep,imp); 578 else 579 idp->current.d_fileno = dbtob(bp->b_blkno) + 580 entryoffsetinblock; 581 582 idp->curroff += reclen; 583 584 switch (imp->iso_ftype) { 585 case ISO_FTYPE_RRIP: 586 cd9660_rrip_getname(ep,idp->current.d_name, &elen, 587 &idp->current.d_fileno,imp); 588 idp->current.d_namlen = (u_char)elen; 589 if (idp->current.d_namlen) 590 error = iso_uiodir(idp,&idp->current,idp->curroff); 591 break; 592 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */ 593 strcpy(idp->current.d_name,".."); 594 switch (ep->name[0]) { 595 case 0: 596 idp->current.d_namlen = 1; 597 error = iso_uiodir(idp,&idp->current,idp->curroff); 598 break; 599 case 1: 600 idp->current.d_namlen = 2; 601 error = iso_uiodir(idp,&idp->current,idp->curroff); 602 break; 603 default: 604 isofntrans(ep->name,idp->current.d_namlen, 605 idp->current.d_name, &elen, 606 imp->iso_ftype == ISO_FTYPE_9660, 607 isonum_711(ep->flags)&4); 608 idp->current.d_namlen = (u_char)elen; 609 if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 610 error = iso_shipdir(idp); 611 else 612 error = iso_uiodir(idp,&idp->current,idp->curroff); 613 break; 614 } 615 } 616 if (error) 617 break; 618 619 entryoffsetinblock += reclen; 620 } 621 622 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 623 idp->current.d_namlen = 0; 624 error = iso_shipdir(idp); 625 } 626 if (error < 0) 627 error = 0; 628 629 if (bp) 630 brelse (bp); 631 uio->uio_offset = idp->uio_off; 632 *ap->a_eofflag = idp->eofflag; 633 634 FREE(idp,M_TEMP); 635 636 return (error); 637 } 638 /* 639 * Return target name of a symbolic link 640 * Shouldn't we get the parent vnode and read the data from there? 641 * This could eventually result in deadlocks in cd9660_lookup. 642 * But otherwise the block read here is in the block buffer two times. 643 */ 644 typedef struct iso_directory_record ISODIR; 645 typedef struct iso_node ISONODE; 646 typedef struct iso_mnt ISOMNT; 647 int 648 cd9660_readlink(ap) 649 struct vop_readlink_args /* { 650 struct vnode *a_vp; 651 struct uio *a_uio; 652 struct ucred *a_cred; 653 } */ *ap; 654 { 655 ISONODE *ip; 656 ISODIR *dirp; 657 ISOMNT *imp; 658 struct buf *bp; 659 u_short symlen; 660 int error; 661 char *symname; 662 ino_t ino; 663 664 ip = VTOI(ap->a_vp); 665 imp = ip->i_mnt; 666 667 if (imp->iso_ftype != ISO_FTYPE_RRIP) 668 return (EINVAL); 669 670 /* 671 * Get parents directory record block that this inode included. 672 */ 673 error = bread(imp->im_devvp, 674 (daddr_t)((ip->i_number&~imp->im_bmask) / DEV_BSIZE), 675 imp->logical_block_size, 676 NOCRED, 677 &bp); 678 if (error) { 679 brelse(bp); 680 return (EINVAL); 681 } 682 683 /* 684 * Setup the directory pointer for this inode 685 */ 686 dirp = (ISODIR *)(bp->b_un.b_addr + (ip->i_number & imp->im_bmask)); 687 688 /* 689 * Just make sure, we have a right one.... 690 * 1: Check not cross boundary on block 691 */ 692 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 693 > imp->logical_block_size) { 694 brelse(bp); 695 return (EINVAL); 696 } 697 698 /* 699 * Now get a buffer 700 * Abuse a namei buffer for now. 701 */ 702 MALLOC(symname,char *,MAXPATHLEN,M_NAMEI,M_WAITOK); 703 704 /* 705 * Ok, we just gathering a symbolic name in SL record. 706 */ 707 if (cd9660_rrip_getsymname(dirp,symname,&symlen,imp) == 0) { 708 FREE(symname,M_NAMEI); 709 brelse(bp); 710 return (EINVAL); 711 } 712 /* 713 * Don't forget before you leave from home ;-) 714 */ 715 brelse(bp); 716 717 /* 718 * return with the symbolic name to caller's. 719 */ 720 error = uiomove(symname,symlen,ap->a_uio); 721 722 FREE(symname,M_NAMEI); 723 724 return (error); 725 } 726 727 /* 728 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually 729 * done. If a buffer has been saved in anticipation of a CREATE, delete it. 730 */ 731 int 732 cd9660_abortop(ap) 733 struct vop_abortop_args /* { 734 struct vnode *a_dvp; 735 struct componentname *a_cnp; 736 } */ *ap; 737 { 738 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 739 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 740 return (0); 741 } 742 743 /* 744 * Lock an inode. 745 */ 746 int 747 cd9660_lock(ap) 748 struct vop_lock_args /* { 749 struct vnode *a_vp; 750 } */ *ap; 751 { 752 register struct vnode *vp = ap->a_vp; 753 register struct iso_node *ip; 754 struct proc *p = curproc; /* XXX */ 755 756 start: 757 while (vp->v_flag & VXLOCK) { 758 vp->v_flag |= VXWANT; 759 sleep((caddr_t)vp, PINOD); 760 } 761 if (vp->v_tag == VT_NON) 762 return (ENOENT); 763 ip = VTOI(vp); 764 if (ip->i_flag & IN_LOCKED) { 765 ip->i_flag |= IN_WANTED; 766 #ifdef DIAGNOSTIC 767 if (p) { 768 if (p->p_pid == ip->i_lockholder) 769 panic("locking against myself"); 770 ip->i_lockwaiter = p->p_pid; 771 } else 772 ip->i_lockwaiter = -1; 773 #endif 774 (void) sleep((caddr_t)ip, PINOD); 775 } 776 #ifdef DIAGNOSTIC 777 ip->i_lockwaiter = 0; 778 if (ip->i_lockholder != 0) 779 panic("lockholder (%d) != 0", ip->i_lockholder); 780 if (p && p->p_pid == 0) 781 printf("locking by process 0\n"); 782 if (p) 783 ip->i_lockholder = p->p_pid; 784 else 785 ip->i_lockholder = -1; 786 #endif 787 ip->i_flag |= IN_LOCKED; 788 return (0); 789 } 790 791 /* 792 * Unlock an inode. 793 */ 794 int 795 cd9660_unlock(ap) 796 struct vop_unlock_args /* { 797 struct vnode *a_vp; 798 } */ *ap; 799 { 800 register struct iso_node *ip = VTOI(ap->a_vp); 801 struct proc *p = curproc; /* XXX */ 802 803 #ifdef DIAGNOSTIC 804 if ((ip->i_flag & IN_LOCKED) == 0) { 805 vprint("ufs_unlock: unlocked inode", ap->a_vp); 806 panic("ufs_unlock NOT LOCKED"); 807 } 808 if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 && 809 ip->i_lockholder > -1/* && lockcount++ < 100*/) 810 panic("unlocker (%d) != lock holder (%d)", 811 p->p_pid, ip->i_lockholder); 812 ip->i_lockholder = 0; 813 #endif 814 ip->i_flag &= ~IN_LOCKED; 815 if (ip->i_flag & IN_WANTED) { 816 ip->i_flag &= ~IN_WANTED; 817 wakeup((caddr_t)ip); 818 } 819 return (0); 820 } 821 822 /* 823 * Check for a locked inode. 824 */ 825 int 826 cd9660_islocked(ap) 827 struct vop_islocked_args /* { 828 struct vnode *a_vp; 829 } */ *ap; 830 { 831 832 if (VTOI(ap->a_vp)->i_flag & IN_LOCKED) 833 return (1); 834 return (0); 835 } 836 837 /* 838 * Calculate the logical to physical mapping if not done already, 839 * then call the device strategy routine. 840 */ 841 int 842 cd9660_strategy(ap) 843 struct vop_strategy_args /* { 844 struct buf *a_bp; 845 } */ *ap; 846 { 847 register struct buf *bp = ap->a_bp; 848 register struct vnode *vp = bp->b_vp; 849 register struct iso_node *ip; 850 int error; 851 852 ip = VTOI(vp); 853 if (vp->v_type == VBLK || vp->v_type == VCHR) 854 panic("cd9660_strategy: spec"); 855 if (bp->b_blkno == bp->b_lblkno) { 856 if (error = 857 VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) { 858 bp->b_error = error; 859 bp->b_flags |= B_ERROR; 860 biodone(bp); 861 return (error); 862 } 863 if ((long)bp->b_blkno == -1) 864 clrbuf(bp); 865 } 866 if ((long)bp->b_blkno == -1) { 867 biodone(bp); 868 return (0); 869 } 870 vp = ip->i_devvp; 871 bp->b_dev = vp->v_rdev; 872 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap); 873 return (0); 874 } 875 876 /* 877 * Print out the contents of an inode. 878 */ 879 int 880 cd9660_print(ap) 881 struct vop_print_args /* { 882 struct vnode *a_vp; 883 } */ *ap; 884 { 885 printf("tag VT_ISOFS, isofs vnode\n"); 886 return (0); 887 } 888 889 /* 890 * Unsupported operation 891 */ 892 int 893 cd9660_enotsupp() 894 { 895 896 return (EOPNOTSUPP); 897 } 898 899 /* 900 * Global vfs data structures for isofs 901 */ 902 #define cd9660_create \ 903 ((int (*) __P((struct vop_create_args *)))cd9660_enotsupp) 904 #define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))cd9660_enotsupp) 905 #define cd9660_setattr \ 906 ((int (*) __P((struct vop_setattr_args *)))cd9660_enotsupp) 907 #define cd9660_write ((int (*) __P((struct vop_write_args *)))cd9660_enotsupp) 908 #define cd9660_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 909 #define cd9660_remove \ 910 ((int (*) __P((struct vop_remove_args *)))cd9660_enotsupp) 911 #define cd9660_link ((int (*) __P((struct vop_link_args *)))cd9660_enotsupp) 912 #define cd9660_rename \ 913 ((int (*) __P((struct vop_rename_args *)))cd9660_enotsupp) 914 #define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))cd9660_enotsupp) 915 #define cd9660_rmdir ((int (*) __P((struct vop_rmdir_args *)))cd9660_enotsupp) 916 #define cd9660_symlink \ 917 ((int (*) __P((struct vop_symlink_args *)))cd9660_enotsupp) 918 #define cd9660_pathconf \ 919 ((int (*) __P((struct vop_pathconf_args *)))cd9660_enotsupp) 920 #define cd9660_advlock \ 921 ((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp) 922 #define cd9660_blkatoff \ 923 ((int (*) __P((struct vop_blkatoff_args *)))cd9660_enotsupp) 924 #define cd9660_valloc ((int(*) __P(( \ 925 struct vnode *pvp, \ 926 int mode, \ 927 struct ucred *cred, \ 928 struct vnode **vpp))) cd9660_enotsupp) 929 #define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))cd9660_enotsupp) 930 #define cd9660_truncate \ 931 ((int (*) __P((struct vop_truncate_args *)))cd9660_enotsupp) 932 #define cd9660_update \ 933 ((int (*) __P((struct vop_update_args *)))cd9660_enotsupp) 934 #define cd9660_bwrite \ 935 ((int (*) __P((struct vop_bwrite_args *)))cd9660_enotsupp) 936 937 /* 938 * Global vfs data structures for nfs 939 */ 940 int (**cd9660_vnodeop_p)(); 941 struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 942 { &vop_default_desc, vn_default_error }, 943 { &vop_lookup_desc, cd9660_lookup }, /* lookup */ 944 { &vop_create_desc, cd9660_create }, /* create */ 945 { &vop_mknod_desc, cd9660_mknod }, /* mknod */ 946 { &vop_open_desc, cd9660_open }, /* open */ 947 { &vop_close_desc, cd9660_close }, /* close */ 948 { &vop_access_desc, cd9660_access }, /* access */ 949 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 950 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 951 { &vop_read_desc, cd9660_read }, /* read */ 952 { &vop_write_desc, cd9660_write }, /* write */ 953 { &vop_ioctl_desc, cd9660_ioctl }, /* ioctl */ 954 { &vop_select_desc, cd9660_select }, /* select */ 955 { &vop_mmap_desc, cd9660_mmap }, /* mmap */ 956 { &vop_fsync_desc, cd9660_fsync }, /* fsync */ 957 { &vop_seek_desc, cd9660_seek }, /* seek */ 958 { &vop_remove_desc, cd9660_remove }, /* remove */ 959 { &vop_link_desc, cd9660_link }, /* link */ 960 { &vop_rename_desc, cd9660_rename }, /* rename */ 961 { &vop_mkdir_desc, cd9660_mkdir }, /* mkdir */ 962 { &vop_rmdir_desc, cd9660_rmdir }, /* rmdir */ 963 { &vop_symlink_desc, cd9660_symlink }, /* symlink */ 964 { &vop_readdir_desc, cd9660_readdir }, /* readdir */ 965 { &vop_readlink_desc, cd9660_readlink },/* readlink */ 966 { &vop_abortop_desc, cd9660_abortop }, /* abortop */ 967 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 968 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 969 { &vop_lock_desc, cd9660_lock }, /* lock */ 970 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 971 { &vop_bmap_desc, cd9660_bmap }, /* bmap */ 972 { &vop_strategy_desc, cd9660_strategy },/* strategy */ 973 { &vop_print_desc, cd9660_print }, /* print */ 974 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 975 { &vop_pathconf_desc, cd9660_pathconf },/* pathconf */ 976 { &vop_advlock_desc, cd9660_advlock }, /* advlock */ 977 { &vop_blkatoff_desc, cd9660_blkatoff },/* blkatoff */ 978 { &vop_valloc_desc, cd9660_valloc }, /* valloc */ 979 { &vop_vfree_desc, cd9660_vfree }, /* vfree */ 980 { &vop_truncate_desc, cd9660_truncate },/* truncate */ 981 { &vop_update_desc, cd9660_update }, /* update */ 982 { &vop_bwrite_desc, vn_bwrite }, 983 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 984 }; 985 struct vnodeopv_desc cd9660_vnodeop_opv_desc = 986 { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 987 988 /* 989 * Special device vnode ops 990 */ 991 int (**cd9660_specop_p)(); 992 struct vnodeopv_entry_desc cd9660_specop_entries[] = { 993 { &vop_default_desc, vn_default_error }, 994 { &vop_lookup_desc, spec_lookup }, /* lookup */ 995 { &vop_create_desc, cd9660_create }, /* create */ 996 { &vop_mknod_desc, cd9660_mknod }, /* mknod */ 997 { &vop_open_desc, spec_open }, /* open */ 998 { &vop_close_desc, spec_close }, /* close */ 999 { &vop_access_desc, cd9660_access }, /* access */ 1000 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1001 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1002 { &vop_read_desc, spec_read }, /* read */ 1003 { &vop_write_desc, spec_write }, /* write */ 1004 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 1005 { &vop_select_desc, spec_select }, /* select */ 1006 { &vop_mmap_desc, spec_mmap }, /* mmap */ 1007 { &vop_fsync_desc, spec_fsync }, /* fsync */ 1008 { &vop_seek_desc, spec_seek }, /* seek */ 1009 { &vop_remove_desc, cd9660_remove }, /* remove */ 1010 { &vop_link_desc, cd9660_link }, /* link */ 1011 { &vop_rename_desc, cd9660_rename }, /* rename */ 1012 { &vop_mkdir_desc, cd9660_mkdir }, /* mkdir */ 1013 { &vop_rmdir_desc, cd9660_rmdir }, /* rmdir */ 1014 { &vop_symlink_desc, cd9660_symlink }, /* symlink */ 1015 { &vop_readdir_desc, spec_readdir }, /* readdir */ 1016 { &vop_readlink_desc, spec_readlink }, /* readlink */ 1017 { &vop_abortop_desc, spec_abortop }, /* abortop */ 1018 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1019 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1020 { &vop_lock_desc, cd9660_lock }, /* lock */ 1021 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1022 { &vop_bmap_desc, spec_bmap }, /* bmap */ 1023 /* XXX strategy: panics, should be notsupp instead? */ 1024 { &vop_strategy_desc, cd9660_strategy },/* strategy */ 1025 { &vop_print_desc, cd9660_print }, /* print */ 1026 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1027 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 1028 { &vop_advlock_desc, spec_advlock }, /* advlock */ 1029 { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 1030 { &vop_valloc_desc, spec_valloc }, /* valloc */ 1031 { &vop_vfree_desc, spec_vfree }, /* vfree */ 1032 { &vop_truncate_desc, spec_truncate }, /* truncate */ 1033 { &vop_update_desc, cd9660_update }, /* update */ 1034 { &vop_bwrite_desc, vn_bwrite }, 1035 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1036 }; 1037 struct vnodeopv_desc cd9660_specop_opv_desc = 1038 { &cd9660_specop_p, cd9660_specop_entries }; 1039 1040 #ifdef FIFO 1041 int (**cd9660_fifoop_p)(); 1042 struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 1043 { &vop_default_desc, vn_default_error }, 1044 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 1045 { &vop_create_desc, cd9660_create }, /* create */ 1046 { &vop_mknod_desc, cd9660_mknod }, /* mknod */ 1047 { &vop_open_desc, fifo_open }, /* open */ 1048 { &vop_close_desc, fifo_close }, /* close */ 1049 { &vop_access_desc, cd9660_access }, /* access */ 1050 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1051 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1052 { &vop_read_desc, fifo_read }, /* read */ 1053 { &vop_write_desc, fifo_write }, /* write */ 1054 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 1055 { &vop_select_desc, fifo_select }, /* select */ 1056 { &vop_mmap_desc, fifo_mmap }, /* mmap */ 1057 { &vop_fsync_desc, fifo_fsync }, /* fsync */ 1058 { &vop_seek_desc, fifo_seek }, /* seek */ 1059 { &vop_remove_desc, cd9660_remove }, /* remove */ 1060 { &vop_link_desc, cd9660_link }, /* link */ 1061 { &vop_rename_desc, cd9660_rename }, /* rename */ 1062 { &vop_mkdir_desc, cd9660_mkdir }, /* mkdir */ 1063 { &vop_rmdir_desc, cd9660_rmdir }, /* rmdir */ 1064 { &vop_symlink_desc, cd9660_symlink }, /* symlink */ 1065 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 1066 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 1067 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 1068 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1069 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1070 { &vop_lock_desc, cd9660_lock }, /* lock */ 1071 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1072 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 1073 { &vop_strategy_desc, fifo_badop }, /* strategy */ 1074 { &vop_print_desc, cd9660_print }, /* print */ 1075 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1076 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 1077 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 1078 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 1079 { &vop_valloc_desc, fifo_valloc }, /* valloc */ 1080 { &vop_vfree_desc, fifo_vfree }, /* vfree */ 1081 { &vop_truncate_desc, fifo_truncate }, /* truncate */ 1082 { &vop_update_desc, cd9660_update }, /* update */ 1083 { &vop_bwrite_desc, vn_bwrite }, 1084 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1085 }; 1086 struct vnodeopv_desc cd9660_fifoop_opv_desc = 1087 { &cd9660_fifoop_p, cd9660_fifoop_entries }; 1088 #endif /* FIFO */ 1089