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 63static vop_setattr_t cd9660_setattr; 64static vop_access_t cd9660_access; 65static vop_getattr_t cd9660_getattr; 66static vop_ioctl_t cd9660_ioctl; 67static vop_pathconf_t cd9660_pathconf; 68static vop_read_t cd9660_read; 69struct isoreaddir; 70static int iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off); 71static int iso_shipdir(struct isoreaddir *idp); 72static vop_readdir_t cd9660_readdir; 73static vop_readlink_t cd9660_readlink; 74static vop_strategy_t cd9660_strategy; 75 76/* 77 * Setattr call. Only allowed for block and character special devices. 78 */ 79static int 80cd9660_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 */ 121static int 122cd9660_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 158static int 159cd9660_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 */ 220static int 221cd9660_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 */ 250static int 251cd9660_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 */ 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_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 */ 614typedef struct iso_directory_record ISODIR; 615typedef struct iso_node ISONODE; 616typedef struct iso_mnt ISOMNT; 617static int 618cd9660_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 */ 709static int 710cd9660_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 = ap->a_vp; 718 struct iso_node *ip; 719 struct bufobj *bo; 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 bp->b_iooffset = dbtob(bp->b_blkno); 735 bo = ip->i_mnt->im_bo;
| 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 63static vop_setattr_t cd9660_setattr; 64static vop_access_t cd9660_access; 65static vop_getattr_t cd9660_getattr; 66static vop_ioctl_t cd9660_ioctl; 67static vop_pathconf_t cd9660_pathconf; 68static vop_read_t cd9660_read; 69struct isoreaddir; 70static int iso_uiodir(struct isoreaddir *idp, struct dirent *dp, off_t off); 71static int iso_shipdir(struct isoreaddir *idp); 72static vop_readdir_t cd9660_readdir; 73static vop_readlink_t cd9660_readlink; 74static vop_strategy_t cd9660_strategy; 75 76/* 77 * Setattr call. Only allowed for block and character special devices. 78 */ 79static int 80cd9660_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 */ 121static int 122cd9660_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 158static int 159cd9660_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 */ 220static int 221cd9660_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 */ 250static int 251cd9660_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 */ 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_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 */ 614typedef struct iso_directory_record ISODIR; 615typedef struct iso_node ISONODE; 616typedef struct iso_mnt ISOMNT; 617static int 618cd9660_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 */ 709static int 710cd9660_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 = ap->a_vp; 718 struct iso_node *ip; 719 struct bufobj *bo; 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 bp->b_iooffset = dbtob(bp->b_blkno); 735 bo = ip->i_mnt->im_bo;
|