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 * 4. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95 35 */ 36 37 #include <sys/cdefs.h> 38 __FBSDID("$FreeBSD$"); 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/namei.h> 43 #include <sys/kernel.h> 44 #include <sys/stat.h> 45 #include <sys/bio.h> 46 #include <sys/buf.h> 47 #include <sys/mount.h> 48 #include <sys/vnode.h> 49 #include <fs/fifofs/fifo.h> 50 #include <sys/malloc.h> 51 #include <sys/dirent.h> 52 #include <sys/unistd.h> 53 #include <sys/filio.h> 54 55 #include <vm/vm.h> 56 #include <vm/vnode_pager.h> 57 #include <vm/uma.h> 58 59 #include <isofs/cd9660/iso.h> 60 #include <isofs/cd9660/cd9660_node.h> 61 #include <isofs/cd9660/iso_rrip.h> 62 63 static int cd9660_setattr(struct vop_setattr_args *); 64 static int cd9660_access(struct vop_access_args *); 65 static int cd9660_getattr(struct vop_getattr_args *); 66 static int cd9660_ioctl(struct vop_ioctl_args *); 67 static int cd9660_pathconf(struct vop_pathconf_args *); 68 static int cd9660_read(struct vop_read_args *); 69 struct isoreaddir; 70 static int iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off); 71 static int iso_shipdir(struct isoreaddir *idp); 72 static int cd9660_readdir(struct vop_readdir_args *); 73 static int cd9660_readlink(struct vop_readlink_args *ap); 74 static int cd9660_strategy(struct vop_strategy_args *); 75 76 /* 77 * Setattr call. Only allowed for block and character special devices. 78 */ 79 static int 80 cd9660_setattr(ap) 81 struct vop_setattr_args /* { 82 struct vnodeop_desc *a_desc; 83 struct vnode *a_vp; 84 struct vattr *a_vap; 85 struct ucred *a_cred; 86 struct thread *a_td; 87 } */ *ap; 88 { 89 struct vnode *vp = ap->a_vp; 90 struct vattr *vap = ap->a_vap; 91 92 if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || 93 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 94 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 95 return (EROFS); 96 if (vap->va_size != (u_quad_t)VNOVAL) { 97 switch (vp->v_type) { 98 case VDIR: 99 return (EISDIR); 100 case VLNK: 101 case VREG: 102 return (EROFS); 103 case VCHR: 104 case VBLK: 105 case VSOCK: 106 case VFIFO: 107 case VNON: 108 case VBAD: 109 return (0); 110 } 111 } 112 return (0); 113 } 114 115 /* 116 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 117 * The mode is shifted to select the owner/group/other fields. The 118 * super user is granted all permissions. 119 */ 120 /* ARGSUSED */ 121 static int 122 cd9660_access(ap) 123 struct vop_access_args /* { 124 struct vnode *a_vp; 125 int a_mode; 126 struct ucred *a_cred; 127 struct thread *a_td; 128 } */ *ap; 129 { 130 struct vnode *vp = ap->a_vp; 131 struct iso_node *ip = VTOI(vp); 132 mode_t mode = ap->a_mode; 133 134 /* 135 * Disallow write attempts unless the file is a socket, 136 * fifo, or a block or character device resident on the 137 * filesystem. 138 */ 139 if (mode & VWRITE) { 140 switch (vp->v_type) { 141 case VDIR: 142 case VLNK: 143 case VREG: 144 return (EROFS); 145 /* NOT REACHED */ 146 default: 147 break; 148 } 149 } 150 151 return (vaccess(vp->v_type, ip->inode.iso_mode, ip->inode.iso_uid, 152 ip->inode.iso_gid, ap->a_mode, ap->a_cred, NULL)); 153 } 154 155 static int 156 cd9660_getattr(ap) 157 struct vop_getattr_args /* { 158 struct vnode *a_vp; 159 struct vattr *a_vap; 160 struct ucred *a_cred; 161 struct thread *a_td; 162 } */ *ap; 163 164 { 165 struct vnode *vp = ap->a_vp; 166 struct vattr *vap = ap->a_vap; 167 struct iso_node *ip = VTOI(vp); 168 169 vap->va_fsid = dev2udev(ip->i_dev); 170 vap->va_fileid = ip->i_number; 171 172 vap->va_mode = ip->inode.iso_mode; 173 vap->va_nlink = ip->inode.iso_links; 174 vap->va_uid = ip->inode.iso_uid; 175 vap->va_gid = ip->inode.iso_gid; 176 vap->va_atime = ip->inode.iso_atime; 177 vap->va_mtime = ip->inode.iso_mtime; 178 vap->va_ctime = ip->inode.iso_ctime; 179 vap->va_rdev = ip->inode.iso_rdev; 180 181 vap->va_size = (u_quad_t) ip->i_size; 182 if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 183 struct vop_readlink_args rdlnk; 184 struct iovec aiov; 185 struct uio auio; 186 char *cp; 187 188 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 189 aiov.iov_base = cp; 190 aiov.iov_len = MAXPATHLEN; 191 auio.uio_iov = &aiov; 192 auio.uio_iovcnt = 1; 193 auio.uio_offset = 0; 194 auio.uio_rw = UIO_READ; 195 auio.uio_segflg = UIO_SYSSPACE; 196 auio.uio_td = ap->a_td; 197 auio.uio_resid = MAXPATHLEN; 198 rdlnk.a_uio = &auio; 199 rdlnk.a_vp = ap->a_vp; 200 rdlnk.a_cred = ap->a_cred; 201 if (cd9660_readlink(&rdlnk) == 0) 202 vap->va_size = MAXPATHLEN - auio.uio_resid; 203 FREE(cp, M_TEMP); 204 } 205 vap->va_flags = 0; 206 vap->va_gen = 1; 207 vap->va_blocksize = ip->i_mnt->logical_block_size; 208 vap->va_bytes = (u_quad_t) ip->i_size; 209 vap->va_type = vp->v_type; 210 vap->va_filerev = 0; 211 return (0); 212 } 213 214 /* 215 * Vnode op for ioctl. 216 */ 217 static int 218 cd9660_ioctl(ap) 219 struct vop_ioctl_args /* { 220 struct vnode *a_vp; 221 u_long a_command; 222 caddr_t a_data; 223 int a_fflag; 224 struct ucred *a_cred; 225 struct thread *a_td; 226 } */ *ap; 227 { 228 struct vnode *vp = ap->a_vp; 229 struct iso_node *ip = VTOI(vp); 230 231 switch (ap->a_command) { 232 233 case FIOGETLBA: 234 *(int *)(ap->a_data) = ip->iso_start; 235 return 0; 236 default: 237 return (ENOTTY); 238 } 239 } 240 241 /* 242 * Vnode op for reading. 243 */ 244 static int 245 cd9660_read(ap) 246 struct vop_read_args /* { 247 struct vnode *a_vp; 248 struct uio *a_uio; 249 int a_ioflag; 250 struct ucred *a_cred; 251 } */ *ap; 252 { 253 struct vnode *vp = ap->a_vp; 254 struct uio *uio = ap->a_uio; 255 struct iso_node *ip = VTOI(vp); 256 struct iso_mnt *imp; 257 struct buf *bp; 258 daddr_t lbn, rablock; 259 off_t diff; 260 int rasize, error = 0; 261 int seqcount; 262 long size, n, on; 263 264 seqcount = ap->a_ioflag >> IO_SEQSHIFT; 265 266 if (uio->uio_resid == 0) 267 return (0); 268 if (uio->uio_offset < 0) 269 return (EINVAL); 270 ip->i_flag |= IN_ACCESS; 271 imp = ip->i_mnt; 272 do { 273 lbn = lblkno(imp, uio->uio_offset); 274 on = blkoff(imp, uio->uio_offset); 275 n = min((u_int)(imp->logical_block_size - on), 276 uio->uio_resid); 277 diff = (off_t)ip->i_size - uio->uio_offset; 278 if (diff <= 0) 279 return (0); 280 if (diff < n) 281 n = diff; 282 size = blksize(imp, ip, lbn); 283 rablock = lbn + 1; 284 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 285 if (lblktosize(imp, rablock) < ip->i_size) 286 error = cluster_read(vp, (off_t)ip->i_size, 287 lbn, size, NOCRED, uio->uio_resid, 288 (ap->a_ioflag >> 16), &bp); 289 else 290 error = bread(vp, lbn, size, NOCRED, &bp); 291 } else { 292 if (seqcount > 1 && 293 lblktosize(imp, rablock) < ip->i_size) { 294 rasize = blksize(imp, ip, rablock); 295 error = breadn(vp, lbn, size, &rablock, 296 &rasize, 1, NOCRED, &bp); 297 } else 298 error = bread(vp, lbn, size, NOCRED, &bp); 299 } 300 n = min(n, size - bp->b_resid); 301 if (error) { 302 brelse(bp); 303 return (error); 304 } 305 306 error = uiomove(bp->b_data + on, (int)n, uio); 307 brelse(bp); 308 } while (error == 0 && uio->uio_resid > 0 && n != 0); 309 return (error); 310 } 311 312 /* 313 * Structure for reading directories 314 */ 315 struct isoreaddir { 316 struct dirent saveent; 317 struct dirent assocent; 318 struct dirent current; 319 off_t saveoff; 320 off_t assocoff; 321 off_t curroff; 322 struct uio *uio; 323 off_t uio_off; 324 int eofflag; 325 u_long *cookies; 326 int ncookies; 327 }; 328 329 static int 330 iso_uiodir(idp,dp,off) 331 struct isoreaddir *idp; 332 struct dirent *dp; 333 off_t off; 334 { 335 int error; 336 337 dp->d_name[dp->d_namlen] = 0; 338 dp->d_reclen = GENERIC_DIRSIZ(dp); 339 340 if (idp->uio->uio_resid < dp->d_reclen) { 341 idp->eofflag = 0; 342 return (-1); 343 } 344 345 if (idp->cookies) { 346 if (idp->ncookies <= 0) { 347 idp->eofflag = 0; 348 return (-1); 349 } 350 351 *idp->cookies++ = off; 352 --idp->ncookies; 353 } 354 355 if ((error = uiomove(dp, dp->d_reclen, idp->uio)) != 0) 356 return (error); 357 idp->uio_off = off; 358 return (0); 359 } 360 361 static int 362 iso_shipdir(idp) 363 struct isoreaddir *idp; 364 { 365 struct dirent *dp; 366 int cl, sl, assoc; 367 int error; 368 char *cname, *sname; 369 370 cl = idp->current.d_namlen; 371 cname = idp->current.d_name; 372 assoc = (cl > 1) && (*cname == ASSOCCHAR); 373 if (assoc) { 374 cl--; 375 cname++; 376 } 377 378 dp = &idp->saveent; 379 sname = dp->d_name; 380 if (!(sl = dp->d_namlen)) { 381 dp = &idp->assocent; 382 sname = dp->d_name + 1; 383 sl = dp->d_namlen - 1; 384 } 385 if (sl > 0) { 386 if (sl != cl 387 || bcmp(sname,cname,sl)) { 388 if (idp->assocent.d_namlen) { 389 if ((error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) != 0) 390 return (error); 391 idp->assocent.d_namlen = 0; 392 } 393 if (idp->saveent.d_namlen) { 394 if ((error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) != 0) 395 return (error); 396 idp->saveent.d_namlen = 0; 397 } 398 } 399 } 400 idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current); 401 if (assoc) { 402 idp->assocoff = idp->curroff; 403 bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 404 } else { 405 idp->saveoff = idp->curroff; 406 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 407 } 408 return (0); 409 } 410 411 /* 412 * Vnode op for readdir 413 */ 414 static int 415 cd9660_readdir(ap) 416 struct vop_readdir_args /* { 417 struct vnode *a_vp; 418 struct uio *a_uio; 419 struct ucred *a_cred; 420 int *a_eofflag; 421 int *a_ncookies; 422 u_long **a_cookies; 423 } */ *ap; 424 { 425 struct uio *uio = ap->a_uio; 426 struct isoreaddir *idp; 427 struct vnode *vdp = ap->a_vp; 428 struct iso_node *dp; 429 struct iso_mnt *imp; 430 struct buf *bp = NULL; 431 struct iso_directory_record *ep; 432 int entryoffsetinblock; 433 doff_t endsearch; 434 u_long bmask; 435 int error = 0; 436 int reclen; 437 u_short namelen; 438 int ncookies = 0; 439 u_long *cookies = NULL; 440 441 dp = VTOI(vdp); 442 imp = dp->i_mnt; 443 bmask = imp->im_bmask; 444 445 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 446 idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 447 /* 448 * XXX 449 * Is it worth trying to figure out the type? 450 */ 451 idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 452 DT_UNKNOWN; 453 idp->uio = uio; 454 if (ap->a_ncookies == NULL) { 455 idp->cookies = NULL; 456 } else { 457 /* 458 * Guess the number of cookies needed. 459 */ 460 ncookies = uio->uio_resid / 16; 461 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), 462 M_TEMP, M_WAITOK); 463 idp->cookies = cookies; 464 idp->ncookies = ncookies; 465 } 466 idp->eofflag = 1; 467 idp->curroff = uio->uio_offset; 468 469 if ((entryoffsetinblock = idp->curroff & bmask) && 470 (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { 471 FREE(idp, M_TEMP); 472 return (error); 473 } 474 endsearch = dp->i_size; 475 476 while (idp->curroff < endsearch) { 477 /* 478 * If offset is on a block boundary, 479 * read the next directory block. 480 * Release previous if it exists. 481 */ 482 if ((idp->curroff & bmask) == 0) { 483 if (bp != NULL) 484 brelse(bp); 485 if ((error = 486 cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp)) != 0) 487 break; 488 entryoffsetinblock = 0; 489 } 490 /* 491 * Get pointer to next entry. 492 */ 493 ep = (struct iso_directory_record *) 494 ((char *)bp->b_data + entryoffsetinblock); 495 496 reclen = isonum_711(ep->length); 497 if (reclen == 0) { 498 /* skip to next block, if any */ 499 idp->curroff = 500 (idp->curroff & ~bmask) + imp->logical_block_size; 501 continue; 502 } 503 504 if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 505 error = EINVAL; 506 /* illegal entry, stop */ 507 break; 508 } 509 510 if (entryoffsetinblock + reclen > imp->logical_block_size) { 511 error = EINVAL; 512 /* illegal directory, so stop looking */ 513 break; 514 } 515 516 idp->current.d_namlen = isonum_711(ep->name_len); 517 518 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 519 error = EINVAL; 520 /* illegal entry, stop */ 521 break; 522 } 523 524 if (isonum_711(ep->flags)&2) 525 idp->current.d_fileno = isodirino(ep, imp); 526 else 527 idp->current.d_fileno = dbtob(bp->b_blkno) + 528 entryoffsetinblock; 529 530 idp->curroff += reclen; 531 532 switch (imp->iso_ftype) { 533 case ISO_FTYPE_RRIP: 534 cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 535 &idp->current.d_fileno,imp); 536 idp->current.d_namlen = (u_char)namelen; 537 if (idp->current.d_namlen) 538 error = iso_uiodir(idp,&idp->current,idp->curroff); 539 break; 540 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ 541 strcpy(idp->current.d_name,".."); 542 if (idp->current.d_namlen == 1 && ep->name[0] == 0) { 543 idp->current.d_namlen = 1; 544 error = iso_uiodir(idp,&idp->current,idp->curroff); 545 } else if (idp->current.d_namlen == 1 && ep->name[0] == 1) { 546 idp->current.d_namlen = 2; 547 error = iso_uiodir(idp,&idp->current,idp->curroff); 548 } else { 549 isofntrans(ep->name,idp->current.d_namlen, 550 idp->current.d_name, &namelen, 551 imp->iso_ftype == ISO_FTYPE_9660, 552 isonum_711(ep->flags)&4, 553 imp->joliet_level, 554 imp->im_flags, 555 imp->im_d2l); 556 idp->current.d_namlen = (u_char)namelen; 557 if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 558 error = iso_shipdir(idp); 559 else 560 error = iso_uiodir(idp,&idp->current,idp->curroff); 561 } 562 } 563 if (error) 564 break; 565 566 entryoffsetinblock += reclen; 567 } 568 569 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 570 idp->current.d_namlen = 0; 571 error = iso_shipdir(idp); 572 } 573 if (error < 0) 574 error = 0; 575 576 if (ap->a_ncookies != NULL) { 577 if (error) 578 free(cookies, M_TEMP); 579 else { 580 /* 581 * Work out the number of cookies actually used. 582 */ 583 *ap->a_ncookies = ncookies - idp->ncookies; 584 *ap->a_cookies = cookies; 585 } 586 } 587 588 if (bp) 589 brelse (bp); 590 591 uio->uio_offset = idp->uio_off; 592 *ap->a_eofflag = idp->eofflag; 593 594 FREE(idp, M_TEMP); 595 596 return (error); 597 } 598 599 /* 600 * Return target name of a symbolic link 601 * Shouldn't we get the parent vnode and read the data from there? 602 * This could eventually result in deadlocks in cd9660_lookup. 603 * But otherwise the block read here is in the block buffer two times. 604 */ 605 typedef struct iso_directory_record ISODIR; 606 typedef struct iso_node ISONODE; 607 typedef struct iso_mnt ISOMNT; 608 static int 609 cd9660_readlink(ap) 610 struct vop_readlink_args /* { 611 struct vnode *a_vp; 612 struct uio *a_uio; 613 struct ucred *a_cred; 614 } */ *ap; 615 { 616 ISONODE *ip; 617 ISODIR *dirp; 618 ISOMNT *imp; 619 struct buf *bp; 620 struct uio *uio; 621 u_short symlen; 622 int error; 623 char *symname; 624 625 ip = VTOI(ap->a_vp); 626 imp = ip->i_mnt; 627 uio = ap->a_uio; 628 629 if (imp->iso_ftype != ISO_FTYPE_RRIP) 630 return (EINVAL); 631 632 /* 633 * Get parents directory record block that this inode included. 634 */ 635 error = bread(imp->im_devvp, 636 (ip->i_number >> imp->im_bshift) << 637 (imp->im_bshift - DEV_BSHIFT), 638 imp->logical_block_size, NOCRED, &bp); 639 if (error) { 640 brelse(bp); 641 return (EINVAL); 642 } 643 644 /* 645 * Setup the directory pointer for this inode 646 */ 647 dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 648 649 /* 650 * Just make sure, we have a right one.... 651 * 1: Check not cross boundary on block 652 */ 653 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 654 > (unsigned)imp->logical_block_size) { 655 brelse(bp); 656 return (EINVAL); 657 } 658 659 /* 660 * Now get a buffer 661 * Abuse a namei buffer for now. 662 */ 663 if (uio->uio_segflg == UIO_SYSSPACE) 664 symname = uio->uio_iov->iov_base; 665 else 666 symname = uma_zalloc(namei_zone, M_WAITOK); 667 668 /* 669 * Ok, we just gathering a symbolic name in SL record. 670 */ 671 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 672 if (uio->uio_segflg != UIO_SYSSPACE) 673 uma_zfree(namei_zone, symname); 674 brelse(bp); 675 return (EINVAL); 676 } 677 /* 678 * Don't forget before you leave from home ;-) 679 */ 680 brelse(bp); 681 682 /* 683 * return with the symbolic name to caller's. 684 */ 685 if (uio->uio_segflg != UIO_SYSSPACE) { 686 error = uiomove(symname, symlen, uio); 687 uma_zfree(namei_zone, symname); 688 return (error); 689 } 690 uio->uio_resid -= symlen; 691 uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen; 692 uio->uio_iov->iov_len -= symlen; 693 return (0); 694 } 695 696 /* 697 * Calculate the logical to physical mapping if not done already, 698 * then call the device strategy routine. 699 */ 700 static int 701 cd9660_strategy(ap) 702 struct vop_strategy_args /* { 703 struct buf *a_vp; 704 struct buf *a_bp; 705 } */ *ap; 706 { 707 struct buf *bp = ap->a_bp; 708 struct vnode *vp = bp->b_vp; 709 struct iso_node *ip; 710 711 KASSERT(ap->a_vp == ap->a_bp->b_vp, ("%s(%p != %p)", 712 __func__, ap->a_vp, ap->a_bp->b_vp)); 713 ip = VTOI(vp); 714 if (vp->v_type == VBLK || vp->v_type == VCHR) 715 panic("cd9660_strategy: spec"); 716 if (bp->b_blkno == bp->b_lblkno) { 717 bp->b_blkno = (ip->iso_start + bp->b_lblkno) << 718 (ip->i_mnt->im_bshift - DEV_BSHIFT); 719 if ((long)bp->b_blkno == -1) /* XXX: cut&paste junk ? */ 720 clrbuf(bp); 721 } 722 if ((long)bp->b_blkno == -1) { /* XXX: cut&paste junk ? */ 723 bufdone(bp); 724 return (0); 725 } 726 vp = ip->i_devvp; 727 bp->b_dev = vp->v_rdev; 728 bp->b_iooffset = dbtob(bp->b_blkno); 729 VOP_SPECSTRATEGY(vp, bp); 730 return (0); 731 } 732 733 /* 734 * Return POSIX pathconf information applicable to cd9660 filesystems. 735 */ 736 static int 737 cd9660_pathconf(ap) 738 struct vop_pathconf_args /* { 739 struct vnode *a_vp; 740 int a_name; 741 register_t *a_retval; 742 } */ *ap; 743 { 744 745 switch (ap->a_name) { 746 case _PC_LINK_MAX: 747 *ap->a_retval = 1; 748 return (0); 749 case _PC_NAME_MAX: 750 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 751 *ap->a_retval = NAME_MAX; 752 else 753 *ap->a_retval = 37; 754 return (0); 755 case _PC_PATH_MAX: 756 *ap->a_retval = PATH_MAX; 757 return (0); 758 case _PC_PIPE_BUF: 759 *ap->a_retval = PIPE_BUF; 760 return (0); 761 case _PC_CHOWN_RESTRICTED: 762 *ap->a_retval = 1; 763 return (0); 764 case _PC_NO_TRUNC: 765 *ap->a_retval = 1; 766 return (0); 767 default: 768 return (EINVAL); 769 } 770 /* NOTREACHED */ 771 } 772 773 /* 774 * Global vfs data structures for cd9660 775 */ 776 vop_t **cd9660_vnodeop_p; 777 static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 778 { &vop_default_desc, (vop_t *) vop_defaultop }, 779 { &vop_access_desc, (vop_t *) cd9660_access }, 780 { &vop_bmap_desc, (vop_t *) cd9660_bmap }, 781 { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, 782 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 783 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 784 { &vop_ioctl_desc, (vop_t *) cd9660_ioctl }, 785 { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, 786 { &vop_pathconf_desc, (vop_t *) cd9660_pathconf }, 787 { &vop_read_desc, (vop_t *) cd9660_read }, 788 { &vop_readdir_desc, (vop_t *) cd9660_readdir }, 789 { &vop_readlink_desc, (vop_t *) cd9660_readlink }, 790 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 791 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 792 { &vop_strategy_desc, (vop_t *) cd9660_strategy }, 793 { NULL, NULL } 794 }; 795 static struct vnodeopv_desc cd9660_vnodeop_opv_desc = 796 { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 797 VNODEOP_SET(cd9660_vnodeop_opv_desc); 798 799 /* 800 * Special device vnode ops 801 */ 802 vop_t **cd9660_specop_p; 803 static struct vnodeopv_entry_desc cd9660_specop_entries[] = { 804 { &vop_default_desc, (vop_t *) spec_vnoperate }, 805 { &vop_access_desc, (vop_t *) cd9660_access }, 806 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 807 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 808 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 809 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 810 { NULL, NULL } 811 }; 812 static struct vnodeopv_desc cd9660_specop_opv_desc = 813 { &cd9660_specop_p, cd9660_specop_entries }; 814 VNODEOP_SET(cd9660_specop_opv_desc); 815 816 vop_t **cd9660_fifoop_p; 817 static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 818 { &vop_default_desc, (vop_t *) fifo_vnoperate }, 819 { &vop_access_desc, (vop_t *) cd9660_access }, 820 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 821 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 822 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 823 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 824 { NULL, NULL } 825 }; 826 static struct vnodeopv_desc cd9660_fifoop_opv_desc = 827 { &cd9660_fifoop_p, cd9660_fifoop_entries }; 828 829 VNODEOP_SET(cd9660_fifoop_opv_desc); 830