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.19 (Berkeley) 5/27/95 39 * $FreeBSD$ 40 */ 41 42 #include <sys/param.h> 43 #include <sys/systm.h> 44 #include <sys/namei.h> 45 #include <sys/kernel.h> 46 #include <sys/stat.h> 47 #include <sys/bio.h> 48 #include <sys/buf.h> 49 #include <sys/mount.h> 50 #include <sys/vnode.h> 51 #include <fs/fifofs/fifo.h> 52 #include <sys/malloc.h> 53 #include <sys/dirent.h> 54 #include <sys/unistd.h> 55 #include <sys/filio.h> 56 57 #include <vm/vm.h> 58 #include <vm/vnode_pager.h> 59 #include <vm/uma.h> 60 61 #include <isofs/cd9660/iso.h> 62 #include <isofs/cd9660/cd9660_node.h> 63 #include <isofs/cd9660/iso_rrip.h> 64 65 static int cd9660_setattr(struct vop_setattr_args *); 66 static int cd9660_access(struct vop_access_args *); 67 static int cd9660_getattr(struct vop_getattr_args *); 68 static int cd9660_ioctl(struct vop_ioctl_args *); 69 static int cd9660_pathconf(struct vop_pathconf_args *); 70 static int cd9660_read(struct vop_read_args *); 71 struct isoreaddir; 72 static int iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off); 73 static int iso_shipdir(struct isoreaddir *idp); 74 static int cd9660_readdir(struct vop_readdir_args *); 75 static int cd9660_readlink(struct vop_readlink_args *ap); 76 static int cd9660_strategy(struct vop_strategy_args *); 77 78 /* 79 * Setattr call. Only allowed for block and character special devices. 80 */ 81 static int 82 cd9660_setattr(ap) 83 struct vop_setattr_args /* { 84 struct vnodeop_desc *a_desc; 85 struct vnode *a_vp; 86 struct vattr *a_vap; 87 struct ucred *a_cred; 88 struct thread *a_td; 89 } */ *ap; 90 { 91 struct vnode *vp = ap->a_vp; 92 struct vattr *vap = ap->a_vap; 93 94 if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || 95 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 96 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 97 return (EROFS); 98 if (vap->va_size != (u_quad_t)VNOVAL) { 99 switch (vp->v_type) { 100 case VDIR: 101 return (EISDIR); 102 case VLNK: 103 case VREG: 104 return (EROFS); 105 case VCHR: 106 case VBLK: 107 case VSOCK: 108 case VFIFO: 109 case VNON: 110 case VBAD: 111 return (0); 112 } 113 } 114 return (0); 115 } 116 117 /* 118 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 119 * The mode is shifted to select the owner/group/other fields. The 120 * super user is granted all permissions. 121 */ 122 /* ARGSUSED */ 123 static int 124 cd9660_access(ap) 125 struct vop_access_args /* { 126 struct vnode *a_vp; 127 int a_mode; 128 struct ucred *a_cred; 129 struct thread *a_td; 130 } */ *ap; 131 { 132 struct vnode *vp = ap->a_vp; 133 struct iso_node *ip = VTOI(vp); 134 mode_t mode = ap->a_mode; 135 136 /* 137 * Disallow write attempts unless the file is a socket, 138 * fifo, or a block or character device resident on the 139 * filesystem. 140 */ 141 if (mode & VWRITE) { 142 switch (vp->v_type) { 143 case VDIR: 144 case VLNK: 145 case VREG: 146 return (EROFS); 147 /* NOT REACHED */ 148 default: 149 break; 150 } 151 } 152 153 return (vaccess(vp->v_type, ip->inode.iso_mode, ip->inode.iso_uid, 154 ip->inode.iso_gid, ap->a_mode, ap->a_cred, NULL)); 155 } 156 157 static int 158 cd9660_getattr(ap) 159 struct vop_getattr_args /* { 160 struct vnode *a_vp; 161 struct vattr *a_vap; 162 struct ucred *a_cred; 163 struct thread *a_td; 164 } */ *ap; 165 166 { 167 struct vnode *vp = ap->a_vp; 168 struct vattr *vap = ap->a_vap; 169 struct iso_node *ip = VTOI(vp); 170 171 vap->va_fsid = dev2udev(ip->i_dev); 172 173 /* 174 * Don't use ip->i_ino for this since it is wrong for hard links. 175 * ip->i_ino should be the same as ip->iso_start (or not exist), 176 * but this currently doesn't work since we abuse it to look up 177 * parent directories from inodes. 178 */ 179 vap->va_fileid = ip->iso_start; 180 181 vap->va_mode = ip->inode.iso_mode; 182 vap->va_nlink = ip->inode.iso_links; 183 vap->va_uid = ip->inode.iso_uid; 184 vap->va_gid = ip->inode.iso_gid; 185 vap->va_atime = ip->inode.iso_atime; 186 vap->va_mtime = ip->inode.iso_mtime; 187 vap->va_ctime = ip->inode.iso_ctime; 188 vap->va_rdev = ip->inode.iso_rdev; 189 190 vap->va_size = (u_quad_t) ip->i_size; 191 if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 192 struct vop_readlink_args rdlnk; 193 struct iovec aiov; 194 struct uio auio; 195 char *cp; 196 197 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 198 aiov.iov_base = cp; 199 aiov.iov_len = MAXPATHLEN; 200 auio.uio_iov = &aiov; 201 auio.uio_iovcnt = 1; 202 auio.uio_offset = 0; 203 auio.uio_rw = UIO_READ; 204 auio.uio_segflg = UIO_SYSSPACE; 205 auio.uio_td = ap->a_td; 206 auio.uio_resid = MAXPATHLEN; 207 rdlnk.a_uio = &auio; 208 rdlnk.a_vp = ap->a_vp; 209 rdlnk.a_cred = ap->a_cred; 210 if (cd9660_readlink(&rdlnk) == 0) 211 vap->va_size = MAXPATHLEN - auio.uio_resid; 212 FREE(cp, M_TEMP); 213 } 214 vap->va_flags = 0; 215 vap->va_gen = 1; 216 vap->va_blocksize = ip->i_mnt->logical_block_size; 217 vap->va_bytes = (u_quad_t) ip->i_size; 218 vap->va_type = vp->v_type; 219 vap->va_filerev = 0; 220 return (0); 221 } 222 223 /* 224 * Vnode op for ioctl. 225 */ 226 static int 227 cd9660_ioctl(ap) 228 struct vop_ioctl_args /* { 229 struct vnode *a_vp; 230 u_long a_command; 231 caddr_t a_data; 232 int a_fflag; 233 struct ucred *a_cred; 234 struct thread *a_td; 235 } */ *ap; 236 { 237 struct vnode *vp = ap->a_vp; 238 struct iso_node *ip = VTOI(vp); 239 240 switch (ap->a_command) { 241 242 case FIOGETLBA: 243 *(int *)(ap->a_data) = ip->iso_start; 244 return 0; 245 default: 246 return (ENOTTY); 247 } 248 } 249 250 /* 251 * Vnode op for reading. 252 */ 253 static int 254 cd9660_read(ap) 255 struct vop_read_args /* { 256 struct vnode *a_vp; 257 struct uio *a_uio; 258 int a_ioflag; 259 struct ucred *a_cred; 260 } */ *ap; 261 { 262 struct vnode *vp = ap->a_vp; 263 struct uio *uio = ap->a_uio; 264 struct iso_node *ip = VTOI(vp); 265 struct iso_mnt *imp; 266 struct buf *bp; 267 daddr_t lbn, rablock; 268 off_t diff; 269 int rasize, error = 0; 270 int seqcount; 271 long size, n, on; 272 273 seqcount = ap->a_ioflag >> 16; 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_int), M_TEMP, 471 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 /* 534 * The "inode number" is iso_start, not i_ino, as in 535 * cd9660_getattr(). 536 */ 537 idp->current.d_fileno = isonum_711(ep->ext_attr_length) + 538 isonum_733(ep->extent); 539 540 idp->curroff += reclen; 541 542 switch (imp->iso_ftype) { 543 case ISO_FTYPE_RRIP: 544 cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 545 &idp->current.d_fileno,imp); 546 idp->current.d_namlen = (u_char)namelen; 547 if (idp->current.d_namlen) 548 error = iso_uiodir(idp,&idp->current,idp->curroff); 549 break; 550 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ 551 strcpy(idp->current.d_name,".."); 552 if (idp->current.d_namlen == 1 && ep->name[0] == 0) { 553 idp->current.d_namlen = 1; 554 error = iso_uiodir(idp,&idp->current,idp->curroff); 555 } else if (idp->current.d_namlen == 1 && ep->name[0] == 1) { 556 idp->current.d_namlen = 2; 557 error = iso_uiodir(idp,&idp->current,idp->curroff); 558 } else { 559 isofntrans(ep->name,idp->current.d_namlen, 560 idp->current.d_name, &namelen, 561 imp->iso_ftype == ISO_FTYPE_9660, 562 isonum_711(ep->flags)&4, 563 imp->joliet_level); 564 idp->current.d_namlen = (u_char)namelen; 565 if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 566 error = iso_shipdir(idp); 567 else 568 error = iso_uiodir(idp,&idp->current,idp->curroff); 569 } 570 } 571 if (error) 572 break; 573 574 entryoffsetinblock += reclen; 575 } 576 577 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 578 idp->current.d_namlen = 0; 579 error = iso_shipdir(idp); 580 } 581 if (error < 0) 582 error = 0; 583 584 if (ap->a_ncookies != NULL) { 585 if (error) 586 free(cookies, M_TEMP); 587 else { 588 /* 589 * Work out the number of cookies actually used. 590 */ 591 *ap->a_ncookies = ncookies - idp->ncookies; 592 *ap->a_cookies = cookies; 593 } 594 } 595 596 if (bp) 597 brelse (bp); 598 599 uio->uio_offset = idp->uio_off; 600 *ap->a_eofflag = idp->eofflag; 601 602 FREE(idp, M_TEMP); 603 604 return (error); 605 } 606 607 /* 608 * Return target name of a symbolic link 609 * Shouldn't we get the parent vnode and read the data from there? 610 * This could eventually result in deadlocks in cd9660_lookup. 611 * But otherwise the block read here is in the block buffer two times. 612 */ 613 typedef struct iso_directory_record ISODIR; 614 typedef struct iso_node ISONODE; 615 typedef struct iso_mnt ISOMNT; 616 static int 617 cd9660_readlink(ap) 618 struct vop_readlink_args /* { 619 struct vnode *a_vp; 620 struct uio *a_uio; 621 struct ucred *a_cred; 622 } */ *ap; 623 { 624 ISONODE *ip; 625 ISODIR *dirp; 626 ISOMNT *imp; 627 struct buf *bp; 628 struct uio *uio; 629 u_short symlen; 630 int error; 631 char *symname; 632 633 ip = VTOI(ap->a_vp); 634 imp = ip->i_mnt; 635 uio = ap->a_uio; 636 637 if (imp->iso_ftype != ISO_FTYPE_RRIP) 638 return (EINVAL); 639 640 /* 641 * Get parents directory record block that this inode included. 642 */ 643 error = bread(imp->im_devvp, 644 (ip->i_number >> imp->im_bshift) << 645 (imp->im_bshift - DEV_BSHIFT), 646 imp->logical_block_size, NOCRED, &bp); 647 if (error) { 648 brelse(bp); 649 return (EINVAL); 650 } 651 652 /* 653 * Setup the directory pointer for this inode 654 */ 655 dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 656 657 /* 658 * Just make sure, we have a right one.... 659 * 1: Check not cross boundary on block 660 */ 661 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 662 > (unsigned)imp->logical_block_size) { 663 brelse(bp); 664 return (EINVAL); 665 } 666 667 /* 668 * Now get a buffer 669 * Abuse a namei buffer for now. 670 */ 671 if (uio->uio_segflg == UIO_SYSSPACE) 672 symname = uio->uio_iov->iov_base; 673 else 674 symname = uma_zalloc(namei_zone, M_WAITOK); 675 676 /* 677 * Ok, we just gathering a symbolic name in SL record. 678 */ 679 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 680 if (uio->uio_segflg != UIO_SYSSPACE) 681 uma_zfree(namei_zone, symname); 682 brelse(bp); 683 return (EINVAL); 684 } 685 /* 686 * Don't forget before you leave from home ;-) 687 */ 688 brelse(bp); 689 690 /* 691 * return with the symbolic name to caller's. 692 */ 693 if (uio->uio_segflg != UIO_SYSSPACE) { 694 error = uiomove(symname, symlen, uio); 695 uma_zfree(namei_zone, symname); 696 return (error); 697 } 698 uio->uio_resid -= symlen; 699 uio->uio_iov->iov_base = (char *)uio->uio_iov->iov_base + symlen; 700 uio->uio_iov->iov_len -= symlen; 701 return (0); 702 } 703 704 /* 705 * Calculate the logical to physical mapping if not done already, 706 * then call the device strategy routine. 707 */ 708 static int 709 cd9660_strategy(ap) 710 struct vop_strategy_args /* { 711 struct buf *a_vp; 712 struct buf *a_bp; 713 } */ *ap; 714 { 715 struct buf *bp = ap->a_bp; 716 struct vnode *vp = bp->b_vp; 717 struct iso_node *ip; 718 719 ip = VTOI(vp); 720 if (vp->v_type == VBLK || vp->v_type == VCHR) 721 panic("cd9660_strategy: spec"); 722 if (bp->b_blkno == bp->b_lblkno) { 723 bp->b_blkno = (ip->iso_start + bp->b_lblkno) << 724 (ip->i_mnt->im_bshift - DEV_BSHIFT); 725 if ((long)bp->b_blkno == -1) /* XXX: cut&paste junk ? */ 726 clrbuf(bp); 727 } 728 if ((long)bp->b_blkno == -1) { /* XXX: cut&paste junk ? */ 729 bufdone(bp); 730 return (0); 731 } 732 vp = ip->i_devvp; 733 bp->b_dev = vp->v_rdev; 734 VOP_SPECSTRATEGY(vp, bp); 735 return (0); 736 } 737 738 /* 739 * Return POSIX pathconf information applicable to cd9660 filesystems. 740 */ 741 static int 742 cd9660_pathconf(ap) 743 struct vop_pathconf_args /* { 744 struct vnode *a_vp; 745 int a_name; 746 register_t *a_retval; 747 } */ *ap; 748 { 749 750 switch (ap->a_name) { 751 case _PC_LINK_MAX: 752 *ap->a_retval = 1; 753 return (0); 754 case _PC_NAME_MAX: 755 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 756 *ap->a_retval = NAME_MAX; 757 else 758 *ap->a_retval = 37; 759 return (0); 760 case _PC_PATH_MAX: 761 *ap->a_retval = PATH_MAX; 762 return (0); 763 case _PC_PIPE_BUF: 764 *ap->a_retval = PIPE_BUF; 765 return (0); 766 case _PC_CHOWN_RESTRICTED: 767 *ap->a_retval = 1; 768 return (0); 769 case _PC_NO_TRUNC: 770 *ap->a_retval = 1; 771 return (0); 772 default: 773 return (EINVAL); 774 } 775 /* NOTREACHED */ 776 } 777 778 /* 779 * Global vfs data structures for cd9660 780 */ 781 vop_t **cd9660_vnodeop_p; 782 static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 783 { &vop_default_desc, (vop_t *) vop_defaultop }, 784 { &vop_access_desc, (vop_t *) cd9660_access }, 785 { &vop_bmap_desc, (vop_t *) cd9660_bmap }, 786 { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, 787 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 788 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 789 { &vop_ioctl_desc, (vop_t *) cd9660_ioctl }, 790 { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, 791 { &vop_pathconf_desc, (vop_t *) cd9660_pathconf }, 792 { &vop_print_desc, (vop_t *) vop_null }, 793 { &vop_read_desc, (vop_t *) cd9660_read }, 794 { &vop_readdir_desc, (vop_t *) cd9660_readdir }, 795 { &vop_readlink_desc, (vop_t *) cd9660_readlink }, 796 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 797 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 798 { &vop_strategy_desc, (vop_t *) cd9660_strategy }, 799 { NULL, NULL } 800 }; 801 static struct vnodeopv_desc cd9660_vnodeop_opv_desc = 802 { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 803 VNODEOP_SET(cd9660_vnodeop_opv_desc); 804 805 /* 806 * Special device vnode ops 807 */ 808 vop_t **cd9660_specop_p; 809 static struct vnodeopv_entry_desc cd9660_specop_entries[] = { 810 { &vop_default_desc, (vop_t *) spec_vnoperate }, 811 { &vop_access_desc, (vop_t *) cd9660_access }, 812 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 813 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 814 { &vop_print_desc, (vop_t *) vop_null }, 815 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 816 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 817 { NULL, NULL } 818 }; 819 static struct vnodeopv_desc cd9660_specop_opv_desc = 820 { &cd9660_specop_p, cd9660_specop_entries }; 821 VNODEOP_SET(cd9660_specop_opv_desc); 822 823 vop_t **cd9660_fifoop_p; 824 static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 825 { &vop_default_desc, (vop_t *) fifo_vnoperate }, 826 { &vop_access_desc, (vop_t *) cd9660_access }, 827 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 828 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 829 { &vop_print_desc, (vop_t *) vop_null }, 830 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 831 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 832 { NULL, NULL } 833 }; 834 static struct vnodeopv_desc cd9660_fifoop_opv_desc = 835 { &cd9660_fifoop_p, cd9660_fifoop_entries }; 836 837 VNODEOP_SET(cd9660_fifoop_opv_desc); 838