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