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