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