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.13 (Berkeley) 11/07/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 if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 216 struct vop_readlink_args rdlnk; 217 struct iovec aiov; 218 struct uio auio; 219 char *cp; 220 221 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 222 aiov.iov_base = cp; 223 aiov.iov_len = MAXPATHLEN; 224 auio.uio_iov = &aiov; 225 auio.uio_iovcnt = 1; 226 auio.uio_offset = 0; 227 auio.uio_rw = UIO_READ; 228 auio.uio_segflg = UIO_SYSSPACE; 229 auio.uio_procp = ap->a_p; 230 auio.uio_resid = MAXPATHLEN; 231 rdlnk.a_uio = &auio; 232 rdlnk.a_vp = ap->a_vp; 233 rdlnk.a_cred = ap->a_cred; 234 if (cd9660_readlink(&rdlnk) == 0) 235 vap->va_size = MAXPATHLEN - auio.uio_resid; 236 FREE(cp, M_TEMP); 237 } 238 vap->va_flags = 0; 239 vap->va_gen = 1; 240 vap->va_blocksize = ip->i_mnt->logical_block_size; 241 vap->va_bytes = (u_quad_t) ip->i_size; 242 vap->va_type = vp->v_type; 243 return (0); 244 } 245 246 #if ISO_DEFAULT_BLOCK_SIZE >= NBPG 247 #ifdef DEBUG 248 extern int doclusterread; 249 #else 250 #define doclusterread 1 251 #endif 252 #else 253 /* XXX until cluster routines can handle block sizes less than one page */ 254 #define doclusterread 0 255 #endif 256 257 /* 258 * Vnode op for reading. 259 */ 260 cd9660_read(ap) 261 struct vop_read_args /* { 262 struct vnode *a_vp; 263 struct uio *a_uio; 264 int a_ioflag; 265 struct ucred *a_cred; 266 } */ *ap; 267 { 268 struct vnode *vp = ap->a_vp; 269 register struct uio *uio = ap->a_uio; 270 register struct iso_node *ip = VTOI(vp); 271 register struct iso_mnt *imp; 272 struct buf *bp; 273 daddr_t lbn, bn, rablock; 274 off_t diff; 275 int rasize, error = 0; 276 long size, n, on; 277 278 if (uio->uio_resid == 0) 279 return (0); 280 if (uio->uio_offset < 0) 281 return (EINVAL); 282 ip->i_flag |= IN_ACCESS; 283 imp = ip->i_mnt; 284 do { 285 lbn = iso_lblkno(imp, uio->uio_offset); 286 on = iso_blkoff(imp, uio->uio_offset); 287 n = min((unsigned)(imp->logical_block_size - on), 288 uio->uio_resid); 289 diff = (off_t)ip->i_size - uio->uio_offset; 290 if (diff <= 0) 291 return (0); 292 if (diff < n) 293 n = diff; 294 size = iso_blksize(imp, ip, lbn); 295 rablock = lbn + 1; 296 if (doclusterread) { 297 if (iso_lblktosize(imp, rablock) <= ip->i_size) 298 error = cluster_read(vp, (off_t)ip->i_size, 299 lbn, size, NOCRED, &bp); 300 else 301 error = bread(vp, lbn, size, NOCRED, &bp); 302 } else { 303 if (vp->v_lastr + 1 == lbn && 304 iso_lblktosize(imp, rablock) < ip->i_size) { 305 rasize = iso_blksize(imp, ip, rablock); 306 error = breadn(vp, lbn, size, &rablock, 307 &rasize, 1, NOCRED, &bp); 308 } else 309 error = bread(vp, lbn, size, NOCRED, &bp); 310 } 311 vp->v_lastr = lbn; 312 n = min(n, size - bp->b_resid); 313 if (error) { 314 brelse(bp); 315 return (error); 316 } 317 318 error = uiomove(bp->b_un.b_addr + on, (int)n, uio); 319 if (n + on == imp->logical_block_size || 320 uio->uio_offset == (off_t)ip->i_size) 321 bp->b_flags |= B_AGE; 322 brelse(bp); 323 } while (error == 0 && uio->uio_resid > 0 && n != 0); 324 return (error); 325 } 326 327 /* ARGSUSED */ 328 int 329 cd9660_ioctl(ap) 330 struct vop_ioctl_args /* { 331 struct vnode *a_vp; 332 int a_command; 333 caddr_t a_data; 334 int a_fflag; 335 struct ucred *a_cred; 336 struct proc *a_p; 337 } */ *ap; 338 { 339 printf("You did ioctl for isofs !!\n"); 340 return (ENOTTY); 341 } 342 343 /* ARGSUSED */ 344 int 345 cd9660_select(ap) 346 struct vop_select_args /* { 347 struct vnode *a_vp; 348 int a_which; 349 int a_fflags; 350 struct ucred *a_cred; 351 struct proc *a_p; 352 } */ *ap; 353 { 354 355 /* 356 * We should really check to see if I/O is possible. 357 */ 358 return (1); 359 } 360 361 /* 362 * Mmap a file 363 * 364 * NB Currently unsupported. 365 */ 366 /* ARGSUSED */ 367 int 368 cd9660_mmap(ap) 369 struct vop_mmap_args /* { 370 struct vnode *a_vp; 371 int a_fflags; 372 struct ucred *a_cred; 373 struct proc *a_p; 374 } */ *ap; 375 { 376 377 return (EINVAL); 378 } 379 380 /* 381 * Seek on a file 382 * 383 * Nothing to do, so just return. 384 */ 385 /* ARGSUSED */ 386 int 387 cd9660_seek(ap) 388 struct vop_seek_args /* { 389 struct vnode *a_vp; 390 off_t a_oldoff; 391 off_t a_newoff; 392 struct ucred *a_cred; 393 } */ *ap; 394 { 395 396 return (0); 397 } 398 399 /* 400 * Structure for reading directories 401 */ 402 struct isoreaddir { 403 struct dirent saveent; 404 struct dirent assocent; 405 struct dirent current; 406 off_t saveoff; 407 off_t assocoff; 408 off_t curroff; 409 struct uio *uio; 410 off_t uio_off; 411 int eofflag; 412 u_long *cookies; 413 int ncookies; 414 }; 415 416 static int 417 iso_uiodir(idp,dp,off) 418 struct isoreaddir *idp; 419 struct dirent *dp; 420 off_t off; 421 { 422 int error; 423 424 dp->d_name[dp->d_namlen] = 0; 425 dp->d_reclen = DIRSIZ(dp); 426 427 if (idp->uio->uio_resid < dp->d_reclen) { 428 idp->eofflag = 0; 429 return (-1); 430 } 431 432 if (idp->cookies) { 433 if (idp->ncookies <= 0) { 434 idp->eofflag = 0; 435 return (-1); 436 } 437 438 *idp->cookies++ = off; 439 --idp->ncookies; 440 } 441 442 if (error = uiomove(dp,dp->d_reclen,idp->uio)) 443 return (error); 444 idp->uio_off = off; 445 return (0); 446 } 447 448 static int 449 iso_shipdir(idp) 450 struct isoreaddir *idp; 451 { 452 struct dirent *dp; 453 int cl, sl, assoc; 454 int error; 455 char *cname, *sname; 456 457 cl = idp->current.d_namlen; 458 cname = idp->current.d_name; 459 if (assoc = cl > 1 && *cname == ASSOCCHAR) { 460 cl--; 461 cname++; 462 } 463 464 dp = &idp->saveent; 465 sname = dp->d_name; 466 if (!(sl = dp->d_namlen)) { 467 dp = &idp->assocent; 468 sname = dp->d_name + 1; 469 sl = dp->d_namlen - 1; 470 } 471 if (sl > 0) { 472 if (sl != cl 473 || bcmp(sname,cname,sl)) { 474 if (idp->assocent.d_namlen) { 475 if (error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) 476 return (error); 477 idp->assocent.d_namlen = 0; 478 } 479 if (idp->saveent.d_namlen) { 480 if (error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) 481 return (error); 482 idp->saveent.d_namlen = 0; 483 } 484 } 485 } 486 idp->current.d_reclen = DIRSIZ(&idp->current); 487 if (assoc) { 488 idp->assocoff = idp->curroff; 489 bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 490 } else { 491 idp->saveoff = idp->curroff; 492 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 493 } 494 return (0); 495 } 496 497 /* 498 * Vnode op for readdir 499 */ 500 int 501 cd9660_readdir(ap) 502 struct vop_readdir_args /* { 503 struct vnode *a_vp; 504 struct uio *a_uio; 505 struct ucred *a_cred; 506 int *a_eofflag; 507 u_long *a_cookies; 508 int a_ncookies; 509 } */ *ap; 510 { 511 register struct uio *uio = ap->a_uio; 512 struct isoreaddir *idp; 513 int entryoffsetinblock; 514 int error = 0; 515 int endsearch; 516 struct iso_directory_record *ep; 517 u_short elen; 518 int reclen; 519 struct iso_mnt *imp; 520 struct iso_node *ip; 521 struct buf *bp = NULL; 522 523 ip = VTOI(ap->a_vp); 524 imp = ip->i_mnt; 525 526 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 527 idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 528 /* 529 * XXX 530 * Is it worth trying to figure out the type? 531 */ 532 idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 533 DT_UNKNOWN; 534 idp->uio = uio; 535 idp->eofflag = 1; 536 idp->cookies = ap->a_cookies; 537 idp->ncookies = ap->a_ncookies; 538 idp->curroff = uio->uio_offset; 539 540 entryoffsetinblock = iso_blkoff(imp, idp->curroff); 541 if (entryoffsetinblock != 0) { 542 if (error = iso_blkatoff(ip, idp->curroff, &bp)) { 543 FREE(idp,M_TEMP); 544 return (error); 545 } 546 } 547 548 endsearch = roundup(ip->i_size, imp->logical_block_size); 549 550 while (idp->curroff < endsearch) { 551 /* 552 * If offset is on a block boundary, 553 * read the next directory block. 554 * Release previous if it exists. 555 */ 556 557 if (iso_blkoff(imp, idp->curroff) == 0) { 558 if (bp != NULL) 559 brelse(bp); 560 if (error = iso_blkatoff(ip, idp->curroff, &bp)) 561 break; 562 entryoffsetinblock = 0; 563 } 564 /* 565 * Get pointer to next entry. 566 */ 567 568 ep = (struct iso_directory_record *) 569 (bp->b_un.b_addr + entryoffsetinblock); 570 571 reclen = isonum_711 (ep->length); 572 if (reclen == 0) { 573 /* skip to next block, if any */ 574 idp->curroff = 575 roundup(idp->curroff, imp->logical_block_size); 576 continue; 577 } 578 579 if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 580 error = EINVAL; 581 /* illegal entry, stop */ 582 break; 583 } 584 585 if (entryoffsetinblock + reclen > imp->logical_block_size) { 586 error = EINVAL; 587 /* illegal directory, so stop looking */ 588 break; 589 } 590 591 idp->current.d_namlen = isonum_711(ep->name_len); 592 593 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 594 error = EINVAL; 595 /* illegal entry, stop */ 596 break; 597 } 598 599 if (isonum_711(ep->flags)&2) 600 isodirino(&idp->current.d_fileno,ep,imp); 601 else 602 idp->current.d_fileno = dbtob(bp->b_blkno) + 603 entryoffsetinblock; 604 605 idp->curroff += reclen; 606 607 switch (imp->iso_ftype) { 608 case ISO_FTYPE_RRIP: 609 cd9660_rrip_getname(ep,idp->current.d_name, &elen, 610 &idp->current.d_fileno,imp); 611 idp->current.d_namlen = (u_char)elen; 612 if (idp->current.d_namlen) 613 error = iso_uiodir(idp,&idp->current,idp->curroff); 614 break; 615 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */ 616 strcpy(idp->current.d_name,".."); 617 switch (ep->name[0]) { 618 case 0: 619 idp->current.d_namlen = 1; 620 error = iso_uiodir(idp,&idp->current,idp->curroff); 621 break; 622 case 1: 623 idp->current.d_namlen = 2; 624 error = iso_uiodir(idp,&idp->current,idp->curroff); 625 break; 626 default: 627 isofntrans(ep->name,idp->current.d_namlen, 628 idp->current.d_name, &elen, 629 imp->iso_ftype == ISO_FTYPE_9660, 630 isonum_711(ep->flags)&4); 631 idp->current.d_namlen = (u_char)elen; 632 if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 633 error = iso_shipdir(idp); 634 else 635 error = iso_uiodir(idp,&idp->current,idp->curroff); 636 break; 637 } 638 } 639 if (error) 640 break; 641 642 entryoffsetinblock += reclen; 643 } 644 645 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 646 idp->current.d_namlen = 0; 647 error = iso_shipdir(idp); 648 } 649 if (error < 0) 650 error = 0; 651 652 if (bp) 653 brelse (bp); 654 uio->uio_offset = idp->uio_off; 655 *ap->a_eofflag = idp->eofflag; 656 657 FREE(idp,M_TEMP); 658 659 return (error); 660 } 661 /* 662 * Return target name of a symbolic link 663 * Shouldn't we get the parent vnode and read the data from there? 664 * This could eventually result in deadlocks in cd9660_lookup. 665 * But otherwise the block read here is in the block buffer two times. 666 */ 667 typedef struct iso_directory_record ISODIR; 668 typedef struct iso_node ISONODE; 669 typedef struct iso_mnt ISOMNT; 670 int 671 cd9660_readlink(ap) 672 struct vop_readlink_args /* { 673 struct vnode *a_vp; 674 struct uio *a_uio; 675 struct ucred *a_cred; 676 } */ *ap; 677 { 678 ISONODE *ip; 679 ISODIR *dirp; 680 ISOMNT *imp; 681 struct buf *bp; 682 struct uio *uio; 683 u_short symlen; 684 int error; 685 char *symname; 686 ino_t ino; 687 688 ip = VTOI(ap->a_vp); 689 imp = ip->i_mnt; 690 uio = ap->a_uio; 691 692 if (imp->iso_ftype != ISO_FTYPE_RRIP) 693 return (EINVAL); 694 695 /* 696 * Get parents directory record block that this inode included. 697 */ 698 error = bread(imp->im_devvp, 699 (daddr_t)((ip->i_number&~imp->im_bmask) / DEV_BSIZE), 700 imp->logical_block_size, 701 NOCRED, 702 &bp); 703 if (error) { 704 brelse(bp); 705 return (EINVAL); 706 } 707 708 /* 709 * Setup the directory pointer for this inode 710 */ 711 dirp = (ISODIR *)(bp->b_un.b_addr + (ip->i_number & imp->im_bmask)); 712 713 /* 714 * Just make sure, we have a right one.... 715 * 1: Check not cross boundary on block 716 */ 717 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 718 > imp->logical_block_size) { 719 brelse(bp); 720 return (EINVAL); 721 } 722 723 /* 724 * Now get a buffer 725 * Abuse a namei buffer for now. 726 */ 727 if (uio->uio_segflg == UIO_SYSSPACE) 728 symname = uio->uio_iov->iov_base; 729 else 730 MALLOC(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 731 732 /* 733 * Ok, we just gathering a symbolic name in SL record. 734 */ 735 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 736 if (uio->uio_segflg != UIO_SYSSPACE) 737 FREE(symname, M_NAMEI); 738 brelse(bp); 739 return (EINVAL); 740 } 741 /* 742 * Don't forget before you leave from home ;-) 743 */ 744 brelse(bp); 745 746 /* 747 * return with the symbolic name to caller's. 748 */ 749 if (uio->uio_segflg != UIO_SYSSPACE) { 750 error = uiomove(symname, symlen, uio); 751 FREE(symname, M_NAMEI); 752 return (error); 753 } 754 uio->uio_resid -= symlen; 755 uio->uio_iov->iov_base += symlen; 756 uio->uio_iov->iov_len -= symlen; 757 return (0); 758 } 759 760 /* 761 * Ufs abort op, called after namei() when a CREATE/DELETE isn't actually 762 * done. If a buffer has been saved in anticipation of a CREATE, delete it. 763 */ 764 int 765 cd9660_abortop(ap) 766 struct vop_abortop_args /* { 767 struct vnode *a_dvp; 768 struct componentname *a_cnp; 769 } */ *ap; 770 { 771 if ((ap->a_cnp->cn_flags & (HASBUF | SAVESTART)) == HASBUF) 772 FREE(ap->a_cnp->cn_pnbuf, M_NAMEI); 773 return (0); 774 } 775 776 /* 777 * Lock an inode. 778 */ 779 int 780 cd9660_lock(ap) 781 struct vop_lock_args /* { 782 struct vnode *a_vp; 783 } */ *ap; 784 { 785 register struct vnode *vp = ap->a_vp; 786 register struct iso_node *ip; 787 struct proc *p = curproc; /* XXX */ 788 789 start: 790 while (vp->v_flag & VXLOCK) { 791 vp->v_flag |= VXWANT; 792 sleep((caddr_t)vp, PINOD); 793 } 794 if (vp->v_tag == VT_NON) 795 return (ENOENT); 796 ip = VTOI(vp); 797 if (ip->i_flag & IN_LOCKED) { 798 ip->i_flag |= IN_WANTED; 799 #ifdef DIAGNOSTIC 800 if (p) { 801 if (p->p_pid == ip->i_lockholder) 802 panic("locking against myself"); 803 ip->i_lockwaiter = p->p_pid; 804 } else 805 ip->i_lockwaiter = -1; 806 #endif 807 (void) sleep((caddr_t)ip, PINOD); 808 } 809 #ifdef DIAGNOSTIC 810 ip->i_lockwaiter = 0; 811 if (ip->i_lockholder != 0) 812 panic("lockholder (%d) != 0", ip->i_lockholder); 813 if (p && p->p_pid == 0) 814 printf("locking by process 0\n"); 815 if (p) 816 ip->i_lockholder = p->p_pid; 817 else 818 ip->i_lockholder = -1; 819 #endif 820 ip->i_flag |= IN_LOCKED; 821 return (0); 822 } 823 824 /* 825 * Unlock an inode. 826 */ 827 int 828 cd9660_unlock(ap) 829 struct vop_unlock_args /* { 830 struct vnode *a_vp; 831 } */ *ap; 832 { 833 register struct iso_node *ip = VTOI(ap->a_vp); 834 struct proc *p = curproc; /* XXX */ 835 836 #ifdef DIAGNOSTIC 837 if ((ip->i_flag & IN_LOCKED) == 0) { 838 vprint("ufs_unlock: unlocked inode", ap->a_vp); 839 panic("ufs_unlock NOT LOCKED"); 840 } 841 if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 && 842 ip->i_lockholder > -1/* && lockcount++ < 100*/) 843 panic("unlocker (%d) != lock holder (%d)", 844 p->p_pid, ip->i_lockholder); 845 ip->i_lockholder = 0; 846 #endif 847 ip->i_flag &= ~IN_LOCKED; 848 if (ip->i_flag & IN_WANTED) { 849 ip->i_flag &= ~IN_WANTED; 850 wakeup((caddr_t)ip); 851 } 852 return (0); 853 } 854 855 /* 856 * Check for a locked inode. 857 */ 858 int 859 cd9660_islocked(ap) 860 struct vop_islocked_args /* { 861 struct vnode *a_vp; 862 } */ *ap; 863 { 864 865 if (VTOI(ap->a_vp)->i_flag & IN_LOCKED) 866 return (1); 867 return (0); 868 } 869 870 /* 871 * Calculate the logical to physical mapping if not done already, 872 * then call the device strategy routine. 873 */ 874 int 875 cd9660_strategy(ap) 876 struct vop_strategy_args /* { 877 struct buf *a_bp; 878 } */ *ap; 879 { 880 register struct buf *bp = ap->a_bp; 881 register struct vnode *vp = bp->b_vp; 882 register struct iso_node *ip; 883 int error; 884 885 ip = VTOI(vp); 886 if (vp->v_type == VBLK || vp->v_type == VCHR) 887 panic("cd9660_strategy: spec"); 888 if (bp->b_blkno == bp->b_lblkno) { 889 if (error = 890 VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) { 891 bp->b_error = error; 892 bp->b_flags |= B_ERROR; 893 biodone(bp); 894 return (error); 895 } 896 if ((long)bp->b_blkno == -1) 897 clrbuf(bp); 898 } 899 if ((long)bp->b_blkno == -1) { 900 biodone(bp); 901 return (0); 902 } 903 vp = ip->i_devvp; 904 bp->b_dev = vp->v_rdev; 905 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap); 906 return (0); 907 } 908 909 /* 910 * Print out the contents of an inode. 911 */ 912 int 913 cd9660_print(ap) 914 struct vop_print_args /* { 915 struct vnode *a_vp; 916 } */ *ap; 917 { 918 printf("tag VT_ISOFS, isofs vnode\n"); 919 return (0); 920 } 921 922 /* 923 * Unsupported operation 924 */ 925 int 926 cd9660_enotsupp() 927 { 928 929 return (EOPNOTSUPP); 930 } 931 932 /* 933 * Global vfs data structures for isofs 934 */ 935 #define cd9660_create \ 936 ((int (*) __P((struct vop_create_args *)))cd9660_enotsupp) 937 #define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))cd9660_enotsupp) 938 #define cd9660_setattr \ 939 ((int (*) __P((struct vop_setattr_args *)))cd9660_enotsupp) 940 #define cd9660_write ((int (*) __P((struct vop_write_args *)))cd9660_enotsupp) 941 #ifdef NFS 942 int lease_check __P((struct vop_lease_args *)); 943 #define cd9660_lease_check lease_check 944 #else 945 #define cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop) 946 #endif 947 #define cd9660_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 948 #define cd9660_remove \ 949 ((int (*) __P((struct vop_remove_args *)))cd9660_enotsupp) 950 #define cd9660_link ((int (*) __P((struct vop_link_args *)))cd9660_enotsupp) 951 #define cd9660_rename \ 952 ((int (*) __P((struct vop_rename_args *)))cd9660_enotsupp) 953 #define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))cd9660_enotsupp) 954 #define cd9660_rmdir ((int (*) __P((struct vop_rmdir_args *)))cd9660_enotsupp) 955 #define cd9660_symlink \ 956 ((int (*) __P((struct vop_symlink_args *)))cd9660_enotsupp) 957 #define cd9660_pathconf \ 958 ((int (*) __P((struct vop_pathconf_args *)))cd9660_enotsupp) 959 #define cd9660_advlock \ 960 ((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp) 961 #define cd9660_blkatoff \ 962 ((int (*) __P((struct vop_blkatoff_args *)))cd9660_enotsupp) 963 #define cd9660_valloc ((int(*) __P(( \ 964 struct vnode *pvp, \ 965 int mode, \ 966 struct ucred *cred, \ 967 struct vnode **vpp))) cd9660_enotsupp) 968 #define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))cd9660_enotsupp) 969 #define cd9660_truncate \ 970 ((int (*) __P((struct vop_truncate_args *)))cd9660_enotsupp) 971 #define cd9660_update \ 972 ((int (*) __P((struct vop_update_args *)))cd9660_enotsupp) 973 #define cd9660_bwrite \ 974 ((int (*) __P((struct vop_bwrite_args *)))cd9660_enotsupp) 975 976 /* 977 * Global vfs data structures for nfs 978 */ 979 int (**cd9660_vnodeop_p)(); 980 struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 981 { &vop_default_desc, vn_default_error }, 982 { &vop_lookup_desc, cd9660_lookup }, /* lookup */ 983 { &vop_create_desc, cd9660_create }, /* create */ 984 { &vop_mknod_desc, cd9660_mknod }, /* mknod */ 985 { &vop_open_desc, cd9660_open }, /* open */ 986 { &vop_close_desc, cd9660_close }, /* close */ 987 { &vop_access_desc, cd9660_access }, /* access */ 988 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 989 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 990 { &vop_read_desc, cd9660_read }, /* read */ 991 { &vop_write_desc, cd9660_write }, /* write */ 992 { &vop_lease_desc, cd9660_lease_check },/* lease */ 993 { &vop_ioctl_desc, cd9660_ioctl }, /* ioctl */ 994 { &vop_select_desc, cd9660_select }, /* select */ 995 { &vop_mmap_desc, cd9660_mmap }, /* mmap */ 996 { &vop_fsync_desc, cd9660_fsync }, /* fsync */ 997 { &vop_seek_desc, cd9660_seek }, /* seek */ 998 { &vop_remove_desc, cd9660_remove }, /* remove */ 999 { &vop_link_desc, cd9660_link }, /* link */ 1000 { &vop_rename_desc, cd9660_rename }, /* rename */ 1001 { &vop_mkdir_desc, cd9660_mkdir }, /* mkdir */ 1002 { &vop_rmdir_desc, cd9660_rmdir }, /* rmdir */ 1003 { &vop_symlink_desc, cd9660_symlink }, /* symlink */ 1004 { &vop_readdir_desc, cd9660_readdir }, /* readdir */ 1005 { &vop_readlink_desc, cd9660_readlink },/* readlink */ 1006 { &vop_abortop_desc, cd9660_abortop }, /* abortop */ 1007 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1008 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1009 { &vop_lock_desc, cd9660_lock }, /* lock */ 1010 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1011 { &vop_bmap_desc, cd9660_bmap }, /* bmap */ 1012 { &vop_strategy_desc, cd9660_strategy },/* strategy */ 1013 { &vop_print_desc, cd9660_print }, /* print */ 1014 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1015 { &vop_pathconf_desc, cd9660_pathconf },/* pathconf */ 1016 { &vop_advlock_desc, cd9660_advlock }, /* advlock */ 1017 { &vop_blkatoff_desc, cd9660_blkatoff },/* blkatoff */ 1018 { &vop_valloc_desc, cd9660_valloc }, /* valloc */ 1019 { &vop_vfree_desc, cd9660_vfree }, /* vfree */ 1020 { &vop_truncate_desc, cd9660_truncate },/* truncate */ 1021 { &vop_update_desc, cd9660_update }, /* update */ 1022 { &vop_bwrite_desc, vn_bwrite }, 1023 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1024 }; 1025 struct vnodeopv_desc cd9660_vnodeop_opv_desc = 1026 { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 1027 1028 /* 1029 * Special device vnode ops 1030 */ 1031 int (**cd9660_specop_p)(); 1032 struct vnodeopv_entry_desc cd9660_specop_entries[] = { 1033 { &vop_default_desc, vn_default_error }, 1034 { &vop_lookup_desc, spec_lookup }, /* lookup */ 1035 { &vop_create_desc, spec_create }, /* create */ 1036 { &vop_mknod_desc, spec_mknod }, /* mknod */ 1037 { &vop_open_desc, spec_open }, /* open */ 1038 { &vop_close_desc, spec_close }, /* close */ 1039 { &vop_access_desc, cd9660_access }, /* access */ 1040 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1041 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1042 { &vop_read_desc, spec_read }, /* read */ 1043 { &vop_write_desc, spec_write }, /* write */ 1044 { &vop_lease_desc, spec_lease_check }, /* lease */ 1045 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 1046 { &vop_select_desc, spec_select }, /* select */ 1047 { &vop_mmap_desc, spec_mmap }, /* mmap */ 1048 { &vop_fsync_desc, spec_fsync }, /* fsync */ 1049 { &vop_seek_desc, spec_seek }, /* seek */ 1050 { &vop_remove_desc, spec_remove }, /* remove */ 1051 { &vop_link_desc, spec_link }, /* link */ 1052 { &vop_rename_desc, spec_rename }, /* rename */ 1053 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 1054 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 1055 { &vop_symlink_desc, spec_symlink }, /* symlink */ 1056 { &vop_readdir_desc, spec_readdir }, /* readdir */ 1057 { &vop_readlink_desc, spec_readlink }, /* readlink */ 1058 { &vop_abortop_desc, spec_abortop }, /* abortop */ 1059 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1060 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1061 { &vop_lock_desc, cd9660_lock }, /* lock */ 1062 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1063 { &vop_bmap_desc, spec_bmap }, /* bmap */ 1064 { &vop_strategy_desc, spec_strategy }, /* strategy */ 1065 { &vop_print_desc, cd9660_print }, /* print */ 1066 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1067 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 1068 { &vop_advlock_desc, spec_advlock }, /* advlock */ 1069 { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 1070 { &vop_valloc_desc, spec_valloc }, /* valloc */ 1071 { &vop_vfree_desc, spec_vfree }, /* vfree */ 1072 { &vop_truncate_desc, spec_truncate }, /* truncate */ 1073 { &vop_update_desc, cd9660_update }, /* update */ 1074 { &vop_bwrite_desc, vn_bwrite }, 1075 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1076 }; 1077 struct vnodeopv_desc cd9660_specop_opv_desc = 1078 { &cd9660_specop_p, cd9660_specop_entries }; 1079 1080 #ifdef FIFO 1081 int (**cd9660_fifoop_p)(); 1082 struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 1083 { &vop_default_desc, vn_default_error }, 1084 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 1085 { &vop_create_desc, fifo_create }, /* create */ 1086 { &vop_mknod_desc, fifo_mknod }, /* mknod */ 1087 { &vop_open_desc, fifo_open }, /* open */ 1088 { &vop_close_desc, fifo_close }, /* close */ 1089 { &vop_access_desc, cd9660_access }, /* access */ 1090 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1091 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1092 { &vop_read_desc, fifo_read }, /* read */ 1093 { &vop_write_desc, fifo_write }, /* write */ 1094 { &vop_lease_desc, fifo_lease_check }, /* lease */ 1095 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 1096 { &vop_select_desc, fifo_select }, /* select */ 1097 { &vop_mmap_desc, fifo_mmap }, /* mmap */ 1098 { &vop_fsync_desc, fifo_fsync }, /* fsync */ 1099 { &vop_seek_desc, fifo_seek }, /* seek */ 1100 { &vop_remove_desc, fifo_remove }, /* remove */ 1101 { &vop_link_desc, fifo_link } , /* link */ 1102 { &vop_rename_desc, fifo_rename }, /* rename */ 1103 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 1104 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 1105 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 1106 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 1107 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 1108 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 1109 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1110 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1111 { &vop_lock_desc, cd9660_lock }, /* lock */ 1112 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1113 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 1114 { &vop_strategy_desc, fifo_strategy }, /* strategy */ 1115 { &vop_print_desc, cd9660_print }, /* print */ 1116 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1117 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 1118 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 1119 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 1120 { &vop_valloc_desc, fifo_valloc }, /* valloc */ 1121 { &vop_vfree_desc, fifo_vfree }, /* vfree */ 1122 { &vop_truncate_desc, fifo_truncate }, /* truncate */ 1123 { &vop_update_desc, cd9660_update }, /* update */ 1124 { &vop_bwrite_desc, vn_bwrite }, 1125 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1126 }; 1127 struct vnodeopv_desc cd9660_fifoop_opv_desc = 1128 { &cd9660_fifoop_p, cd9660_fifoop_entries }; 1129 #endif /* FIFO */ 1130