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.16 (Berkeley) 02/27/95 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; 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 = lblkno(imp, uio->uio_offset); 286 on = blkoff(imp, uio->uio_offset); 287 n = min((u_int)(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 = blksize(imp, ip, lbn); 295 rablock = lbn + 1; 296 if (doclusterread) { 297 if (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 lblktosize(imp, rablock) < ip->i_size) { 305 rasize = 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_data + 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 u_long 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 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 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 struct vnode *vdp = ap->a_vp; 514 struct iso_node *dp; 515 struct iso_mnt *imp; 516 struct buf *bp = NULL; 517 struct iso_directory_record *ep; 518 int entryoffsetinblock; 519 doff_t endsearch; 520 u_long bmask; 521 int error = 0; 522 int reclen; 523 u_short namelen; 524 525 dp = VTOI(vdp); 526 imp = dp->i_mnt; 527 bmask = imp->im_bmask; 528 529 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 530 idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 531 /* 532 * XXX 533 * Is it worth trying to figure out the type? 534 */ 535 idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 536 DT_UNKNOWN; 537 idp->uio = uio; 538 idp->eofflag = 1; 539 idp->cookies = ap->a_cookies; 540 idp->ncookies = ap->a_ncookies; 541 idp->curroff = uio->uio_offset; 542 543 if ((entryoffsetinblock = idp->curroff & bmask) && 544 (error = VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp))) { 545 FREE(idp, M_TEMP); 546 return (error); 547 } 548 endsearch = dp->i_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 if ((idp->curroff & bmask) == 0) { 557 if (bp != NULL) 558 brelse(bp); 559 if (error = 560 VOP_BLKATOFF(vdp, (off_t)idp->curroff, NULL, &bp)) 561 break; 562 entryoffsetinblock = 0; 563 } 564 /* 565 * Get pointer to next entry. 566 */ 567 ep = (struct iso_directory_record *) 568 ((char *)bp->b_data + entryoffsetinblock); 569 570 reclen = isonum_711(ep->length); 571 if (reclen == 0) { 572 /* skip to next block, if any */ 573 idp->curroff = 574 (idp->curroff & ~bmask) + imp->logical_block_size; 575 continue; 576 } 577 578 if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 579 error = EINVAL; 580 /* illegal entry, stop */ 581 break; 582 } 583 584 if (entryoffsetinblock + reclen > imp->logical_block_size) { 585 error = EINVAL; 586 /* illegal directory, so stop looking */ 587 break; 588 } 589 590 idp->current.d_namlen = isonum_711(ep->name_len); 591 592 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 593 error = EINVAL; 594 /* illegal entry, stop */ 595 break; 596 } 597 598 if (isonum_711(ep->flags)&2) 599 idp->current.d_fileno = isodirino(ep, imp); 600 else 601 idp->current.d_fileno = dbtob(bp->b_blkno) + 602 entryoffsetinblock; 603 604 idp->curroff += reclen; 605 606 switch (imp->iso_ftype) { 607 case ISO_FTYPE_RRIP: 608 cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 609 &idp->current.d_fileno,imp); 610 idp->current.d_namlen = (u_char)namelen; 611 if (idp->current.d_namlen) 612 error = iso_uiodir(idp,&idp->current,idp->curroff); 613 break; 614 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */ 615 strcpy(idp->current.d_name,".."); 616 switch (ep->name[0]) { 617 case 0: 618 idp->current.d_namlen = 1; 619 error = iso_uiodir(idp,&idp->current,idp->curroff); 620 break; 621 case 1: 622 idp->current.d_namlen = 2; 623 error = iso_uiodir(idp,&idp->current,idp->curroff); 624 break; 625 default: 626 isofntrans(ep->name,idp->current.d_namlen, 627 idp->current.d_name, &namelen, 628 imp->iso_ftype == ISO_FTYPE_9660, 629 isonum_711(ep->flags)&4); 630 idp->current.d_namlen = (u_char)namelen; 631 if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 632 error = iso_shipdir(idp); 633 else 634 error = iso_uiodir(idp,&idp->current,idp->curroff); 635 break; 636 } 637 } 638 if (error) 639 break; 640 641 entryoffsetinblock += reclen; 642 } 643 644 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 645 idp->current.d_namlen = 0; 646 error = iso_shipdir(idp); 647 } 648 if (error < 0) 649 error = 0; 650 651 if (bp) 652 brelse (bp); 653 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 /* 663 * Return target name of a symbolic link 664 * Shouldn't we get the parent vnode and read the data from there? 665 * This could eventually result in deadlocks in cd9660_lookup. 666 * But otherwise the block read here is in the block buffer two times. 667 */ 668 typedef struct iso_directory_record ISODIR; 669 typedef struct iso_node ISONODE; 670 typedef struct iso_mnt ISOMNT; 671 int 672 cd9660_readlink(ap) 673 struct vop_readlink_args /* { 674 struct vnode *a_vp; 675 struct uio *a_uio; 676 struct ucred *a_cred; 677 } */ *ap; 678 { 679 ISONODE *ip; 680 ISODIR *dirp; 681 ISOMNT *imp; 682 struct buf *bp; 683 struct uio *uio; 684 u_short symlen; 685 int error; 686 char *symname; 687 ino_t ino; 688 689 ip = VTOI(ap->a_vp); 690 imp = ip->i_mnt; 691 uio = ap->a_uio; 692 693 if (imp->iso_ftype != ISO_FTYPE_RRIP) 694 return (EINVAL); 695 696 /* 697 * Get parents directory record block that this inode included. 698 */ 699 error = bread(imp->im_devvp, 700 (ip->i_number >> imp->im_bshift) << 701 (imp->im_bshift - DEV_BSHIFT), 702 imp->logical_block_size, NOCRED, &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_data + (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 * Calculate the logical to physical mapping if not done already, 857 * then call the device strategy routine. 858 */ 859 int 860 cd9660_strategy(ap) 861 struct vop_strategy_args /* { 862 struct buf *a_bp; 863 } */ *ap; 864 { 865 register struct buf *bp = ap->a_bp; 866 register struct vnode *vp = bp->b_vp; 867 register struct iso_node *ip; 868 int error; 869 870 ip = VTOI(vp); 871 if (vp->v_type == VBLK || vp->v_type == VCHR) 872 panic("cd9660_strategy: spec"); 873 if (bp->b_blkno == bp->b_lblkno) { 874 if (error = 875 VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) { 876 bp->b_error = error; 877 bp->b_flags |= B_ERROR; 878 biodone(bp); 879 return (error); 880 } 881 if ((long)bp->b_blkno == -1) 882 clrbuf(bp); 883 } 884 if ((long)bp->b_blkno == -1) { 885 biodone(bp); 886 return (0); 887 } 888 vp = ip->i_devvp; 889 bp->b_dev = vp->v_rdev; 890 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap); 891 return (0); 892 } 893 894 /* 895 * Print out the contents of an inode. 896 */ 897 int 898 cd9660_print(ap) 899 struct vop_print_args /* { 900 struct vnode *a_vp; 901 } */ *ap; 902 { 903 904 printf("tag VT_ISOFS, isofs vnode\n"); 905 return (0); 906 } 907 908 /* 909 * Check for a locked inode. 910 */ 911 int 912 cd9660_islocked(ap) 913 struct vop_islocked_args /* { 914 struct vnode *a_vp; 915 } */ *ap; 916 { 917 918 if (VTOI(ap->a_vp)->i_flag & IN_LOCKED) 919 return (1); 920 return (0); 921 } 922 923 /* 924 * Return POSIX pathconf information applicable to cd9660 filesystems. 925 */ 926 int 927 cd9660_pathconf(ap) 928 struct vop_pathconf_args /* { 929 struct vnode *a_vp; 930 int a_name; 931 register_t *a_retval; 932 } */ *ap; 933 { 934 935 switch (ap->a_name) { 936 case _PC_LINK_MAX: 937 *ap->a_retval = 1; 938 return (0); 939 case _PC_NAME_MAX: 940 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 941 *ap->a_retval = NAME_MAX; 942 else 943 *ap->a_retval = 37; 944 return (0); 945 case _PC_PATH_MAX: 946 *ap->a_retval = PATH_MAX; 947 return (0); 948 case _PC_PIPE_BUF: 949 *ap->a_retval = PIPE_BUF; 950 return (0); 951 case _PC_CHOWN_RESTRICTED: 952 *ap->a_retval = 1; 953 return (0); 954 case _PC_NO_TRUNC: 955 *ap->a_retval = 1; 956 return (0); 957 default: 958 return (EINVAL); 959 } 960 /* NOTREACHED */ 961 } 962 963 /* 964 * Unsupported operation 965 */ 966 int 967 cd9660_enotsupp() 968 { 969 970 return (EOPNOTSUPP); 971 } 972 973 /* 974 * Global vfs data structures for isofs 975 */ 976 #define cd9660_create \ 977 ((int (*) __P((struct vop_create_args *)))cd9660_enotsupp) 978 #define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))cd9660_enotsupp) 979 #define cd9660_setattr \ 980 ((int (*) __P((struct vop_setattr_args *)))cd9660_enotsupp) 981 #define cd9660_write ((int (*) __P((struct vop_write_args *)))cd9660_enotsupp) 982 #ifdef NFS 983 int lease_check __P((struct vop_lease_args *)); 984 #define cd9660_lease_check lease_check 985 #else 986 #define cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop) 987 #endif 988 #define cd9660_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 989 #define cd9660_remove \ 990 ((int (*) __P((struct vop_remove_args *)))cd9660_enotsupp) 991 #define cd9660_link ((int (*) __P((struct vop_link_args *)))cd9660_enotsupp) 992 #define cd9660_rename \ 993 ((int (*) __P((struct vop_rename_args *)))cd9660_enotsupp) 994 #define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))cd9660_enotsupp) 995 #define cd9660_rmdir ((int (*) __P((struct vop_rmdir_args *)))cd9660_enotsupp) 996 #define cd9660_symlink \ 997 ((int (*) __P((struct vop_symlink_args *)))cd9660_enotsupp) 998 #define cd9660_advlock \ 999 ((int (*) __P((struct vop_advlock_args *)))cd9660_enotsupp) 1000 #define cd9660_valloc ((int(*) __P(( \ 1001 struct vnode *pvp, \ 1002 int mode, \ 1003 struct ucred *cred, \ 1004 struct vnode **vpp))) cd9660_enotsupp) 1005 #define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))cd9660_enotsupp) 1006 #define cd9660_truncate \ 1007 ((int (*) __P((struct vop_truncate_args *)))cd9660_enotsupp) 1008 #define cd9660_update \ 1009 ((int (*) __P((struct vop_update_args *)))cd9660_enotsupp) 1010 #define cd9660_bwrite \ 1011 ((int (*) __P((struct vop_bwrite_args *)))cd9660_enotsupp) 1012 1013 /* 1014 * Global vfs data structures for cd9660 1015 */ 1016 int (**cd9660_vnodeop_p)(); 1017 struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 1018 { &vop_default_desc, vn_default_error }, 1019 { &vop_lookup_desc, cd9660_lookup }, /* lookup */ 1020 { &vop_create_desc, cd9660_create }, /* create */ 1021 { &vop_mknod_desc, cd9660_mknod }, /* mknod */ 1022 { &vop_open_desc, cd9660_open }, /* open */ 1023 { &vop_close_desc, cd9660_close }, /* close */ 1024 { &vop_access_desc, cd9660_access }, /* access */ 1025 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1026 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1027 { &vop_read_desc, cd9660_read }, /* read */ 1028 { &vop_write_desc, cd9660_write }, /* write */ 1029 { &vop_lease_desc, cd9660_lease_check },/* lease */ 1030 { &vop_ioctl_desc, cd9660_ioctl }, /* ioctl */ 1031 { &vop_select_desc, cd9660_select }, /* select */ 1032 { &vop_revoke_desc, cd9660_revoke }, /* revoke */ 1033 { &vop_mmap_desc, cd9660_mmap }, /* mmap */ 1034 { &vop_fsync_desc, cd9660_fsync }, /* fsync */ 1035 { &vop_seek_desc, cd9660_seek }, /* seek */ 1036 { &vop_remove_desc, cd9660_remove }, /* remove */ 1037 { &vop_link_desc, cd9660_link }, /* link */ 1038 { &vop_rename_desc, cd9660_rename }, /* rename */ 1039 { &vop_mkdir_desc, cd9660_mkdir }, /* mkdir */ 1040 { &vop_rmdir_desc, cd9660_rmdir }, /* rmdir */ 1041 { &vop_symlink_desc, cd9660_symlink }, /* symlink */ 1042 { &vop_readdir_desc, cd9660_readdir }, /* readdir */ 1043 { &vop_readlink_desc, cd9660_readlink },/* readlink */ 1044 { &vop_abortop_desc, cd9660_abortop }, /* abortop */ 1045 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1046 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1047 { &vop_lock_desc, cd9660_lock }, /* lock */ 1048 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1049 { &vop_bmap_desc, cd9660_bmap }, /* bmap */ 1050 { &vop_strategy_desc, cd9660_strategy },/* strategy */ 1051 { &vop_print_desc, cd9660_print }, /* print */ 1052 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1053 { &vop_pathconf_desc, cd9660_pathconf },/* pathconf */ 1054 { &vop_advlock_desc, cd9660_advlock }, /* advlock */ 1055 { &vop_blkatoff_desc, cd9660_blkatoff },/* blkatoff */ 1056 { &vop_valloc_desc, cd9660_valloc }, /* valloc */ 1057 { &vop_vfree_desc, cd9660_vfree }, /* vfree */ 1058 { &vop_truncate_desc, cd9660_truncate },/* truncate */ 1059 { &vop_update_desc, cd9660_update }, /* update */ 1060 { &vop_bwrite_desc, vn_bwrite }, 1061 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1062 }; 1063 struct vnodeopv_desc cd9660_vnodeop_opv_desc = 1064 { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 1065 1066 /* 1067 * Special device vnode ops 1068 */ 1069 int (**cd9660_specop_p)(); 1070 struct vnodeopv_entry_desc cd9660_specop_entries[] = { 1071 { &vop_default_desc, vn_default_error }, 1072 { &vop_lookup_desc, spec_lookup }, /* lookup */ 1073 { &vop_create_desc, spec_create }, /* create */ 1074 { &vop_mknod_desc, spec_mknod }, /* mknod */ 1075 { &vop_open_desc, spec_open }, /* open */ 1076 { &vop_close_desc, spec_close }, /* close */ 1077 { &vop_access_desc, cd9660_access }, /* access */ 1078 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1079 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1080 { &vop_read_desc, spec_read }, /* read */ 1081 { &vop_write_desc, spec_write }, /* write */ 1082 { &vop_lease_desc, spec_lease_check }, /* lease */ 1083 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 1084 { &vop_select_desc, spec_select }, /* select */ 1085 { &vop_revoke_desc, spec_revoke }, /* revoke */ 1086 { &vop_mmap_desc, spec_mmap }, /* mmap */ 1087 { &vop_fsync_desc, spec_fsync }, /* fsync */ 1088 { &vop_seek_desc, spec_seek }, /* seek */ 1089 { &vop_remove_desc, spec_remove }, /* remove */ 1090 { &vop_link_desc, spec_link }, /* link */ 1091 { &vop_rename_desc, spec_rename }, /* rename */ 1092 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 1093 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 1094 { &vop_symlink_desc, spec_symlink }, /* symlink */ 1095 { &vop_readdir_desc, spec_readdir }, /* readdir */ 1096 { &vop_readlink_desc, spec_readlink }, /* readlink */ 1097 { &vop_abortop_desc, spec_abortop }, /* abortop */ 1098 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1099 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1100 { &vop_lock_desc, cd9660_lock }, /* lock */ 1101 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1102 { &vop_bmap_desc, spec_bmap }, /* bmap */ 1103 { &vop_strategy_desc, spec_strategy }, /* strategy */ 1104 { &vop_print_desc, cd9660_print }, /* print */ 1105 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1106 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 1107 { &vop_advlock_desc, spec_advlock }, /* advlock */ 1108 { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 1109 { &vop_valloc_desc, spec_valloc }, /* valloc */ 1110 { &vop_vfree_desc, spec_vfree }, /* vfree */ 1111 { &vop_truncate_desc, spec_truncate }, /* truncate */ 1112 { &vop_update_desc, cd9660_update }, /* update */ 1113 { &vop_bwrite_desc, vn_bwrite }, 1114 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1115 }; 1116 struct vnodeopv_desc cd9660_specop_opv_desc = 1117 { &cd9660_specop_p, cd9660_specop_entries }; 1118 1119 #ifdef FIFO 1120 int (**cd9660_fifoop_p)(); 1121 struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 1122 { &vop_default_desc, vn_default_error }, 1123 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 1124 { &vop_create_desc, fifo_create }, /* create */ 1125 { &vop_mknod_desc, fifo_mknod }, /* mknod */ 1126 { &vop_open_desc, fifo_open }, /* open */ 1127 { &vop_close_desc, fifo_close }, /* close */ 1128 { &vop_access_desc, cd9660_access }, /* access */ 1129 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1130 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1131 { &vop_read_desc, fifo_read }, /* read */ 1132 { &vop_write_desc, fifo_write }, /* write */ 1133 { &vop_lease_desc, fifo_lease_check }, /* lease */ 1134 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 1135 { &vop_select_desc, fifo_select }, /* select */ 1136 { &vop_revoke_desc, fifo_revoke }, /* revoke */ 1137 { &vop_mmap_desc, fifo_mmap }, /* mmap */ 1138 { &vop_fsync_desc, fifo_fsync }, /* fsync */ 1139 { &vop_seek_desc, fifo_seek }, /* seek */ 1140 { &vop_remove_desc, fifo_remove }, /* remove */ 1141 { &vop_link_desc, fifo_link } , /* link */ 1142 { &vop_rename_desc, fifo_rename }, /* rename */ 1143 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 1144 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 1145 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 1146 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 1147 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 1148 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 1149 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1150 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1151 { &vop_lock_desc, cd9660_lock }, /* lock */ 1152 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1153 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 1154 { &vop_strategy_desc, fifo_strategy }, /* strategy */ 1155 { &vop_print_desc, cd9660_print }, /* print */ 1156 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1157 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 1158 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 1159 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 1160 { &vop_valloc_desc, fifo_valloc }, /* valloc */ 1161 { &vop_vfree_desc, fifo_vfree }, /* vfree */ 1162 { &vop_truncate_desc, fifo_truncate }, /* truncate */ 1163 { &vop_update_desc, cd9660_update }, /* update */ 1164 { &vop_bwrite_desc, vn_bwrite }, 1165 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1166 }; 1167 struct vnodeopv_desc cd9660_fifoop_opv_desc = 1168 { &cd9660_fifoop_p, cd9660_fifoop_entries }; 1169 #endif /* FIFO */ 1170