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 static int cd9660_print(struct vop_print_args *); 78 79 /* 80 * Setattr call. Only allowed for block and character special devices. 81 */ 82 int 83 cd9660_setattr(ap) 84 struct vop_setattr_args /* { 85 struct vnodeop_desc *a_desc; 86 struct vnode *a_vp; 87 struct vattr *a_vap; 88 struct ucred *a_cred; 89 struct thread *a_td; 90 } */ *ap; 91 { 92 struct vnode *vp = ap->a_vp; 93 struct vattr *vap = ap->a_vap; 94 95 if (vap->va_flags != (u_long)VNOVAL || vap->va_uid != (uid_t)VNOVAL || 96 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 97 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 98 return (EROFS); 99 if (vap->va_size != (u_quad_t)VNOVAL) { 100 switch (vp->v_type) { 101 case VDIR: 102 return (EISDIR); 103 case VLNK: 104 case VREG: 105 return (EROFS); 106 case VCHR: 107 case VBLK: 108 case VSOCK: 109 case VFIFO: 110 case VNON: 111 case VBAD: 112 return (0); 113 } 114 } 115 return (0); 116 } 117 118 /* 119 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 120 * The mode is shifted to select the owner/group/other fields. The 121 * super user is granted all permissions. 122 */ 123 /* ARGSUSED */ 124 static int 125 cd9660_access(ap) 126 struct vop_access_args /* { 127 struct vnode *a_vp; 128 int a_mode; 129 struct ucred *a_cred; 130 struct thread *a_td; 131 } */ *ap; 132 { 133 struct vnode *vp = ap->a_vp; 134 struct iso_node *ip = VTOI(vp); 135 mode_t mode = ap->a_mode; 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 register struct vattr *vap = ap->a_vap; 170 register struct iso_node *ip = VTOI(vp); 171 172 vap->va_fsid = dev2udev(ip->i_dev); 173 174 /* 175 * Don't use ip->i_ino for this since it is wrong for hard links. 176 * ip->i_ino should be the same as ip->iso_start (or not exist), 177 * but this currently doesn't work since we abuse it to look up 178 * parent directories from inodes. 179 */ 180 vap->va_fileid = ip->iso_start; 181 182 vap->va_mode = ip->inode.iso_mode; 183 vap->va_nlink = ip->inode.iso_links; 184 vap->va_uid = ip->inode.iso_uid; 185 vap->va_gid = ip->inode.iso_gid; 186 vap->va_atime = ip->inode.iso_atime; 187 vap->va_mtime = ip->inode.iso_mtime; 188 vap->va_ctime = ip->inode.iso_ctime; 189 vap->va_rdev = ip->inode.iso_rdev; 190 191 vap->va_size = (u_quad_t) ip->i_size; 192 if (ip->i_size == 0 && (vap->va_mode & S_IFMT) == S_IFLNK) { 193 struct vop_readlink_args rdlnk; 194 struct iovec aiov; 195 struct uio auio; 196 char *cp; 197 198 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 199 aiov.iov_base = cp; 200 aiov.iov_len = MAXPATHLEN; 201 auio.uio_iov = &aiov; 202 auio.uio_iovcnt = 1; 203 auio.uio_offset = 0; 204 auio.uio_rw = UIO_READ; 205 auio.uio_segflg = UIO_SYSSPACE; 206 auio.uio_td = ap->a_td; 207 auio.uio_resid = MAXPATHLEN; 208 rdlnk.a_uio = &auio; 209 rdlnk.a_vp = ap->a_vp; 210 rdlnk.a_cred = ap->a_cred; 211 if (cd9660_readlink(&rdlnk) == 0) 212 vap->va_size = MAXPATHLEN - auio.uio_resid; 213 FREE(cp, M_TEMP); 214 } 215 vap->va_flags = 0; 216 vap->va_gen = 1; 217 vap->va_blocksize = ip->i_mnt->logical_block_size; 218 vap->va_bytes = (u_quad_t) ip->i_size; 219 vap->va_type = vp->v_type; 220 vap->va_filerev = 0; 221 return (0); 222 } 223 224 /* 225 * Vnode op for ioctl. 226 */ 227 static int 228 cd9660_ioctl(ap) 229 struct vop_ioctl_args /* { 230 struct vnode *a_vp; 231 int a_command; 232 caddr_t a_data; 233 int a_fflag; 234 struct ucred *a_cred; 235 struct thread *a_td; 236 } */ *ap; 237 { 238 struct vnode *vp = ap->a_vp; 239 struct iso_node *ip = VTOI(vp); 240 241 switch (ap->a_command) { 242 243 case FIOGETLBA: 244 *(int *)(ap->a_data) = ip->iso_start; 245 return 0; 246 default: 247 return (ENOTTY); 248 } 249 } 250 251 /* 252 * Vnode op for reading. 253 */ 254 static int 255 cd9660_read(ap) 256 struct vop_read_args /* { 257 struct vnode *a_vp; 258 struct uio *a_uio; 259 int a_ioflag; 260 struct ucred *a_cred; 261 } */ *ap; 262 { 263 struct vnode *vp = ap->a_vp; 264 register struct uio *uio = ap->a_uio; 265 register struct iso_node *ip = VTOI(vp); 266 register struct iso_mnt *imp; 267 struct buf *bp; 268 daddr_t lbn, rablock; 269 off_t diff; 270 int rasize, error = 0; 271 int seqcount; 272 long size, n, on; 273 274 seqcount = ap->a_ioflag >> 16; 275 276 if (uio->uio_resid == 0) 277 return (0); 278 if (uio->uio_offset < 0) 279 return (EINVAL); 280 ip->i_flag |= IN_ACCESS; 281 imp = ip->i_mnt; 282 do { 283 lbn = lblkno(imp, uio->uio_offset); 284 on = blkoff(imp, uio->uio_offset); 285 n = min((u_int)(imp->logical_block_size - on), 286 uio->uio_resid); 287 diff = (off_t)ip->i_size - uio->uio_offset; 288 if (diff <= 0) 289 return (0); 290 if (diff < n) 291 n = diff; 292 size = blksize(imp, ip, lbn); 293 rablock = lbn + 1; 294 if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0) { 295 if (lblktosize(imp, rablock) < ip->i_size) 296 error = cluster_read(vp, (off_t)ip->i_size, 297 lbn, size, NOCRED, uio->uio_resid, 298 (ap->a_ioflag >> 16), &bp); 299 else 300 error = bread(vp, lbn, size, NOCRED, &bp); 301 } else { 302 if (seqcount > 1 && 303 lblktosize(imp, rablock) < ip->i_size) { 304 rasize = blksize(imp, ip, rablock); 305 error = breadn(vp, lbn, size, &rablock, 306 &rasize, 1, NOCRED, &bp); 307 } else 308 error = bread(vp, lbn, size, NOCRED, &bp); 309 } 310 n = min(n, size - bp->b_resid); 311 if (error) { 312 brelse(bp); 313 return (error); 314 } 315 316 error = uiomove(bp->b_data + on, (int)n, uio); 317 brelse(bp); 318 } while (error == 0 && uio->uio_resid > 0 && n != 0); 319 return (error); 320 } 321 322 /* 323 * Structure for reading directories 324 */ 325 struct isoreaddir { 326 struct dirent saveent; 327 struct dirent assocent; 328 struct dirent current; 329 off_t saveoff; 330 off_t assocoff; 331 off_t curroff; 332 struct uio *uio; 333 off_t uio_off; 334 int eofflag; 335 u_long *cookies; 336 int ncookies; 337 }; 338 339 int 340 iso_uiodir(idp,dp,off) 341 struct isoreaddir *idp; 342 struct dirent *dp; 343 off_t off; 344 { 345 int error; 346 347 dp->d_name[dp->d_namlen] = 0; 348 dp->d_reclen = GENERIC_DIRSIZ(dp); 349 350 if (idp->uio->uio_resid < dp->d_reclen) { 351 idp->eofflag = 0; 352 return (-1); 353 } 354 355 if (idp->cookies) { 356 if (idp->ncookies <= 0) { 357 idp->eofflag = 0; 358 return (-1); 359 } 360 361 *idp->cookies++ = off; 362 --idp->ncookies; 363 } 364 365 if ((error = uiomove((caddr_t) dp,dp->d_reclen,idp->uio)) != 0) 366 return (error); 367 idp->uio_off = off; 368 return (0); 369 } 370 371 int 372 iso_shipdir(idp) 373 struct isoreaddir *idp; 374 { 375 struct dirent *dp; 376 int cl, sl, assoc; 377 int error; 378 char *cname, *sname; 379 380 cl = idp->current.d_namlen; 381 cname = idp->current.d_name; 382 assoc = (cl > 1) && (*cname == ASSOCCHAR); 383 if (assoc) { 384 cl--; 385 cname++; 386 } 387 388 dp = &idp->saveent; 389 sname = dp->d_name; 390 if (!(sl = dp->d_namlen)) { 391 dp = &idp->assocent; 392 sname = dp->d_name + 1; 393 sl = dp->d_namlen - 1; 394 } 395 if (sl > 0) { 396 if (sl != cl 397 || bcmp(sname,cname,sl)) { 398 if (idp->assocent.d_namlen) { 399 if ((error = iso_uiodir(idp,&idp->assocent,idp->assocoff)) != 0) 400 return (error); 401 idp->assocent.d_namlen = 0; 402 } 403 if (idp->saveent.d_namlen) { 404 if ((error = iso_uiodir(idp,&idp->saveent,idp->saveoff)) != 0) 405 return (error); 406 idp->saveent.d_namlen = 0; 407 } 408 } 409 } 410 idp->current.d_reclen = GENERIC_DIRSIZ(&idp->current); 411 if (assoc) { 412 idp->assocoff = idp->curroff; 413 bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 414 } else { 415 idp->saveoff = idp->curroff; 416 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 417 } 418 return (0); 419 } 420 421 /* 422 * Vnode op for readdir 423 */ 424 static int 425 cd9660_readdir(ap) 426 struct vop_readdir_args /* { 427 struct vnode *a_vp; 428 struct uio *a_uio; 429 struct ucred *a_cred; 430 int *a_eofflag; 431 int *a_ncookies; 432 u_long *a_cookies; 433 } */ *ap; 434 { 435 register struct uio *uio = ap->a_uio; 436 struct isoreaddir *idp; 437 struct vnode *vdp = ap->a_vp; 438 struct iso_node *dp; 439 struct iso_mnt *imp; 440 struct buf *bp = NULL; 441 struct iso_directory_record *ep; 442 int entryoffsetinblock; 443 doff_t endsearch; 444 u_long bmask; 445 int error = 0; 446 int reclen; 447 u_short namelen; 448 int ncookies = 0; 449 u_long *cookies = NULL; 450 451 dp = VTOI(vdp); 452 imp = dp->i_mnt; 453 bmask = imp->im_bmask; 454 455 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 456 idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 457 /* 458 * XXX 459 * Is it worth trying to figure out the type? 460 */ 461 idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 462 DT_UNKNOWN; 463 idp->uio = uio; 464 if (ap->a_ncookies == NULL) { 465 idp->cookies = NULL; 466 } else { 467 /* 468 * Guess the number of cookies needed. 469 */ 470 ncookies = uio->uio_resid / 16; 471 MALLOC(cookies, u_long *, ncookies * sizeof(u_int), M_TEMP, 472 M_WAITOK); 473 idp->cookies = cookies; 474 idp->ncookies = ncookies; 475 } 476 idp->eofflag = 1; 477 idp->curroff = uio->uio_offset; 478 479 if ((entryoffsetinblock = idp->curroff & bmask) && 480 (error = cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { 481 FREE(idp, M_TEMP); 482 return (error); 483 } 484 endsearch = dp->i_size; 485 486 while (idp->curroff < endsearch) { 487 /* 488 * If offset is on a block boundary, 489 * read the next directory block. 490 * Release previous if it exists. 491 */ 492 if ((idp->curroff & bmask) == 0) { 493 if (bp != NULL) 494 brelse(bp); 495 if ((error = 496 cd9660_blkatoff(vdp, (off_t)idp->curroff, NULL, &bp)) != 0) 497 break; 498 entryoffsetinblock = 0; 499 } 500 /* 501 * Get pointer to next entry. 502 */ 503 ep = (struct iso_directory_record *) 504 ((char *)bp->b_data + entryoffsetinblock); 505 506 reclen = isonum_711(ep->length); 507 if (reclen == 0) { 508 /* skip to next block, if any */ 509 idp->curroff = 510 (idp->curroff & ~bmask) + imp->logical_block_size; 511 continue; 512 } 513 514 if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 515 error = EINVAL; 516 /* illegal entry, stop */ 517 break; 518 } 519 520 if (entryoffsetinblock + reclen > imp->logical_block_size) { 521 error = EINVAL; 522 /* illegal directory, so stop looking */ 523 break; 524 } 525 526 idp->current.d_namlen = isonum_711(ep->name_len); 527 528 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 529 error = EINVAL; 530 /* illegal entry, stop */ 531 break; 532 } 533 534 /* 535 * The "inode number" is iso_start, not i_ino, as in 536 * cd9660_getattr(). 537 */ 538 idp->current.d_fileno = isonum_711(ep->ext_attr_length) + 539 isonum_733(ep->extent); 540 541 idp->curroff += reclen; 542 543 switch (imp->iso_ftype) { 544 case ISO_FTYPE_RRIP: 545 cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 546 &idp->current.d_fileno,imp); 547 idp->current.d_namlen = (u_char)namelen; 548 if (idp->current.d_namlen) 549 error = iso_uiodir(idp,&idp->current,idp->curroff); 550 break; 551 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 || ISO_FTYPE_HIGH_SIERRA*/ 552 strcpy(idp->current.d_name,".."); 553 if (idp->current.d_namlen == 1 && ep->name[0] == 0) { 554 idp->current.d_namlen = 1; 555 error = iso_uiodir(idp,&idp->current,idp->curroff); 556 } else if (idp->current.d_namlen == 1 && ep->name[0] == 1) { 557 idp->current.d_namlen = 2; 558 error = iso_uiodir(idp,&idp->current,idp->curroff); 559 } else { 560 isofntrans(ep->name,idp->current.d_namlen, 561 idp->current.d_name, &namelen, 562 imp->iso_ftype == ISO_FTYPE_9660, 563 isonum_711(ep->flags)&4, 564 imp->joliet_level); 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 += 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 register struct buf *bp = ap->a_bp; 717 register struct vnode *vp = bp->b_vp; 718 register struct iso_node *ip; 719 720 ip = VTOI(vp); 721 if (vp->v_type == VBLK || vp->v_type == VCHR) 722 panic("cd9660_strategy: spec"); 723 if (bp->b_blkno == bp->b_lblkno) { 724 bp->b_blkno = (ip->iso_start + bp->b_lblkno) << 725 (ip->i_mnt->im_bshift - DEV_BSHIFT); 726 if ((long)bp->b_blkno == -1) /* XXX: cut&paste junk ? */ 727 clrbuf(bp); 728 } 729 if ((long)bp->b_blkno == -1) { /* XXX: cut&paste junk ? */ 730 bufdone(bp); 731 return (0); 732 } 733 vp = ip->i_devvp; 734 bp->b_dev = vp->v_rdev; 735 VOP_STRATEGY(vp, bp); 736 return (0); 737 } 738 739 /* 740 * Print out the contents of an inode. 741 */ 742 static int 743 cd9660_print(ap) 744 struct vop_print_args /* { 745 struct vnode *a_vp; 746 } */ *ap; 747 { 748 749 printf("tag VT_ISOFS, isofs vnode\n"); 750 return (0); 751 } 752 753 /* 754 * Return POSIX pathconf information applicable to cd9660 filesystems. 755 */ 756 static int 757 cd9660_pathconf(ap) 758 struct vop_pathconf_args /* { 759 struct vnode *a_vp; 760 int a_name; 761 register_t *a_retval; 762 } */ *ap; 763 { 764 765 switch (ap->a_name) { 766 case _PC_LINK_MAX: 767 *ap->a_retval = 1; 768 return (0); 769 case _PC_NAME_MAX: 770 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 771 *ap->a_retval = NAME_MAX; 772 else 773 *ap->a_retval = 37; 774 return (0); 775 case _PC_PATH_MAX: 776 *ap->a_retval = PATH_MAX; 777 return (0); 778 case _PC_PIPE_BUF: 779 *ap->a_retval = PIPE_BUF; 780 return (0); 781 case _PC_CHOWN_RESTRICTED: 782 *ap->a_retval = 1; 783 return (0); 784 case _PC_NO_TRUNC: 785 *ap->a_retval = 1; 786 return (0); 787 default: 788 return (EINVAL); 789 } 790 /* NOTREACHED */ 791 } 792 793 /* 794 * Global vfs data structures for cd9660 795 */ 796 vop_t **cd9660_vnodeop_p; 797 static struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 798 { &vop_default_desc, (vop_t *) vop_defaultop }, 799 { &vop_access_desc, (vop_t *) cd9660_access }, 800 { &vop_bmap_desc, (vop_t *) cd9660_bmap }, 801 { &vop_cachedlookup_desc, (vop_t *) cd9660_lookup }, 802 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 803 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 804 { &vop_ioctl_desc, (vop_t *) cd9660_ioctl }, 805 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 806 { &vop_lock_desc, (vop_t *) vop_stdlock }, 807 { &vop_lookup_desc, (vop_t *) vfs_cache_lookup }, 808 { &vop_pathconf_desc, (vop_t *) cd9660_pathconf }, 809 { &vop_print_desc, (vop_t *) cd9660_print }, 810 { &vop_read_desc, (vop_t *) cd9660_read }, 811 { &vop_readdir_desc, (vop_t *) cd9660_readdir }, 812 { &vop_readlink_desc, (vop_t *) cd9660_readlink }, 813 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 814 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 815 { &vop_strategy_desc, (vop_t *) cd9660_strategy }, 816 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 817 { NULL, NULL } 818 }; 819 static struct vnodeopv_desc cd9660_vnodeop_opv_desc = 820 { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 821 VNODEOP_SET(cd9660_vnodeop_opv_desc); 822 823 /* 824 * Special device vnode ops 825 */ 826 vop_t **cd9660_specop_p; 827 static struct vnodeopv_entry_desc cd9660_specop_entries[] = { 828 { &vop_default_desc, (vop_t *) spec_vnoperate }, 829 { &vop_access_desc, (vop_t *) cd9660_access }, 830 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 831 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 832 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 833 { &vop_lock_desc, (vop_t *) vop_stdlock }, 834 { &vop_print_desc, (vop_t *) cd9660_print }, 835 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 836 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 837 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 838 { NULL, NULL } 839 }; 840 static struct vnodeopv_desc cd9660_specop_opv_desc = 841 { &cd9660_specop_p, cd9660_specop_entries }; 842 VNODEOP_SET(cd9660_specop_opv_desc); 843 844 vop_t **cd9660_fifoop_p; 845 static struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 846 { &vop_default_desc, (vop_t *) fifo_vnoperate }, 847 { &vop_access_desc, (vop_t *) cd9660_access }, 848 { &vop_getattr_desc, (vop_t *) cd9660_getattr }, 849 { &vop_inactive_desc, (vop_t *) cd9660_inactive }, 850 { &vop_islocked_desc, (vop_t *) vop_stdislocked }, 851 { &vop_lock_desc, (vop_t *) vop_stdlock }, 852 { &vop_print_desc, (vop_t *) cd9660_print }, 853 { &vop_reclaim_desc, (vop_t *) cd9660_reclaim }, 854 { &vop_setattr_desc, (vop_t *) cd9660_setattr }, 855 { &vop_unlock_desc, (vop_t *) vop_stdunlock }, 856 { NULL, NULL } 857 }; 858 static struct vnodeopv_desc cd9660_fifoop_opv_desc = 859 { &cd9660_fifoop_p, cd9660_fifoop_entries }; 860 861 VNODEOP_SET(cd9660_fifoop_opv_desc); 862