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