1 /* $OpenBSD: cd9660_vnops.c,v 1.19 2001/12/10 18:49:51 art Exp $ */ 2 /* $NetBSD: cd9660_vnops.c,v 1.42 1997/10/16 23:56:57 christos Exp $ */ 3 4 /*- 5 * Copyright (c) 1994 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley 9 * by Pace Willisson (pace@blitz.com). The Rock Ridge Extension 10 * Support code is derived from software contributed to Berkeley 11 * by Atsushi Murai (amurai@spec.co.jp). 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * @(#)cd9660_vnops.c 8.15 (Berkeley) 12/5/94 42 */ 43 44 #include <sys/param.h> 45 #include <sys/systm.h> 46 #include <sys/namei.h> 47 #include <sys/resourcevar.h> 48 #include <sys/kernel.h> 49 #include <sys/file.h> 50 #include <sys/stat.h> 51 #include <sys/buf.h> 52 #include <sys/proc.h> 53 #include <sys/conf.h> 54 #include <sys/mount.h> 55 #include <sys/vnode.h> 56 #include <sys/malloc.h> 57 #include <sys/dirent.h> 58 #include <sys/ioctl.h> 59 #include <sys/ioccom.h> 60 #include <sys/cdio.h> 61 62 #include <miscfs/fifofs/fifo.h> 63 #include <miscfs/specfs/specdev.h> 64 65 #include <isofs/cd9660/iso.h> 66 #include <isofs/cd9660/cd9660_extern.h> 67 #include <isofs/cd9660/cd9660_node.h> 68 #include <isofs/cd9660/iso_rrip.h> 69 70 /* 71 * Structure for reading directories 72 */ 73 struct isoreaddir { 74 struct dirent saveent; 75 struct dirent assocent; 76 struct dirent current; 77 off_t saveoff; 78 off_t assocoff; 79 off_t curroff; 80 struct uio *uio; 81 off_t uio_off; 82 int eofflag; 83 u_long *cookies; 84 int ncookies; 85 }; 86 87 int iso_uiodir __P((struct isoreaddir *, struct dirent *, off_t)); 88 int iso_shipdir __P((struct isoreaddir *)); 89 90 #if 0 91 /* 92 * Mknod vnode call 93 * Actually remap the device number 94 */ 95 int 96 cd9660_mknod(ndp, vap, cred, p) 97 struct nameidata *ndp; 98 struct ucred *cred; 99 struct vattr *vap; 100 struct proc *p; 101 { 102 #ifndef ISODEVMAP 103 free(ndp->ni_pnbuf, M_NAMEI); 104 vput(ndp->ni_dvp); 105 vput(ndp->ni_vp); 106 return (EINVAL); 107 #else 108 register struct vnode *vp; 109 struct iso_node *ip; 110 struct iso_dnode *dp; 111 int error; 112 113 vp = ndp->ni_vp; 114 ip = VTOI(vp); 115 116 if (ip->i_mnt->iso_ftype != ISO_FTYPE_RRIP 117 || vap->va_type != vp->v_type 118 || (vap->va_type != VCHR && vap->va_type != VBLK)) { 119 free(ndp->ni_pnbuf, M_NAMEI); 120 vput(ndp->ni_dvp); 121 vput(ndp->ni_vp); 122 return (EINVAL); 123 } 124 125 dp = iso_dmap(ip->i_dev,ip->i_number,1); 126 if (ip->inode.iso_rdev == vap->va_rdev || vap->va_rdev == VNOVAL) { 127 /* same as the unmapped one, delete the mapping */ 128 remque(dp); 129 FREE(dp, M_CACHE); 130 } else 131 /* enter new mapping */ 132 dp->d_dev = vap->va_rdev; 133 134 /* 135 * Remove inode so that it will be reloaded by iget and 136 * checked to see if it is an alias of an existing entry 137 * in the inode cache. 138 */ 139 vput(vp); 140 vp->v_type = VNON; 141 vgone(vp); 142 return (0); 143 #endif 144 } 145 #endif 146 147 /* 148 * Setattr call. Only allowed for block and character special devices. 149 */ 150 int 151 cd9660_setattr(v) 152 void *v; 153 { 154 struct vop_setattr_args /* { 155 struct vnodeop_desc *a_desc; 156 struct vnode *a_vp; 157 struct vattr *a_vap; 158 struct ucred *a_cred; 159 struct proc *a_p; 160 } */ *ap = v; 161 struct vnode *vp = ap->a_vp; 162 struct vattr *vap = ap->a_vap; 163 164 if (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || 165 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 166 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) 167 return (EROFS); 168 if (vap->va_size != VNOVAL) { 169 switch (vp->v_type) { 170 case VDIR: 171 return (EISDIR); 172 case VLNK: 173 case VREG: 174 return (EROFS); 175 case VCHR: 176 case VBLK: 177 case VSOCK: 178 case VFIFO: 179 return (0); 180 default: 181 return (EINVAL); 182 } 183 } 184 185 return (EINVAL); 186 } 187 188 /* 189 * Open called. 190 * 191 * Nothing to do. 192 */ 193 /* ARGSUSED */ 194 int 195 cd9660_open(v) 196 void *v; 197 { 198 return (0); 199 } 200 201 /* 202 * Close called 203 * 204 * Update the times on the inode on writeable file systems. 205 */ 206 /* ARGSUSED */ 207 int 208 cd9660_close(v) 209 void *v; 210 { 211 return (0); 212 } 213 214 /* 215 * Check mode permission on inode pointer. Mode is READ, WRITE or EXEC. 216 * The mode is shifted to select the owner/group/other fields. The 217 * super user is granted all permissions. 218 */ 219 int 220 cd9660_access(v) 221 void *v; 222 { 223 struct vop_access_args /* { 224 struct vnode *a_vp; 225 int a_mode; 226 struct ucred *a_cred; 227 struct proc *a_p; 228 } */ *ap = v; 229 struct iso_node *ip = VTOI(ap->a_vp); 230 231 return (vaccess(ip->inode.iso_mode & ALLPERMS, ip->inode.iso_uid, 232 ip->inode.iso_gid, ap->a_mode, ap->a_cred)); 233 } 234 235 int 236 cd9660_getattr(v) 237 void *v; 238 { 239 struct vop_getattr_args /* { 240 struct vnode *a_vp; 241 struct vattr *a_vap; 242 struct ucred *a_cred; 243 struct proc *a_p; 244 } */ *ap = v; 245 struct vnode *vp = ap->a_vp; 246 register struct vattr *vap = ap->a_vap; 247 register struct iso_node *ip = VTOI(vp); 248 249 vap->va_fsid = ip->i_dev; 250 vap->va_fileid = ip->i_number; 251 252 vap->va_mode = ip->inode.iso_mode & ALLPERMS; 253 vap->va_nlink = ip->inode.iso_links; 254 vap->va_uid = ip->inode.iso_uid; 255 vap->va_gid = ip->inode.iso_gid; 256 vap->va_atime = ip->inode.iso_atime; 257 vap->va_mtime = ip->inode.iso_mtime; 258 vap->va_ctime = ip->inode.iso_ctime; 259 vap->va_rdev = ip->inode.iso_rdev; 260 261 vap->va_size = (u_quad_t) ip->i_size; 262 if (ip->i_size == 0 && vp->v_type == VLNK) { 263 struct vop_readlink_args rdlnk; 264 struct iovec aiov; 265 struct uio auio; 266 char *cp; 267 268 MALLOC(cp, char *, MAXPATHLEN, M_TEMP, M_WAITOK); 269 aiov.iov_base = cp; 270 aiov.iov_len = MAXPATHLEN; 271 auio.uio_iov = &aiov; 272 auio.uio_iovcnt = 1; 273 auio.uio_offset = 0; 274 auio.uio_rw = UIO_READ; 275 auio.uio_segflg = UIO_SYSSPACE; 276 auio.uio_procp = ap->a_p; 277 auio.uio_resid = MAXPATHLEN; 278 rdlnk.a_uio = &auio; 279 rdlnk.a_vp = ap->a_vp; 280 rdlnk.a_cred = ap->a_cred; 281 if (cd9660_readlink(&rdlnk) == 0) 282 vap->va_size = MAXPATHLEN - auio.uio_resid; 283 FREE(cp, M_TEMP); 284 } 285 vap->va_flags = 0; 286 vap->va_gen = 1; 287 vap->va_blocksize = ip->i_mnt->logical_block_size; 288 vap->va_bytes = (u_quad_t) ip->i_size; 289 vap->va_type = vp->v_type; 290 return (0); 291 } 292 293 /* 294 * Vnode op for reading. 295 */ 296 int 297 cd9660_read(v) 298 void *v; 299 { 300 struct vop_read_args /* { 301 struct vnode *a_vp; 302 struct uio *a_uio; 303 int a_ioflag; 304 struct ucred *a_cred; 305 } */ *ap = v; 306 struct vnode *vp = ap->a_vp; 307 struct uio *uio = ap->a_uio; 308 struct iso_node *ip = VTOI(vp); 309 int error; 310 311 if (uio->uio_resid == 0) 312 return (0); 313 if (uio->uio_offset < 0) 314 return (EINVAL); 315 316 if (vp->v_type != VREG) { 317 /* 318 * XXXART - maybe we should just panic? this is not possible 319 * unless vn_rdwr is called with VDIR and that's an error. 320 */ 321 return (EISDIR); 322 } 323 324 ip->i_flag |= IN_ACCESS; 325 326 while (uio->uio_resid > 0) { 327 void *win; 328 vsize_t bytelen = MIN(ip->i_size - uio->uio_offset, 329 uio->uio_resid); 330 if (bytelen == 0) 331 break; 332 win = ubc_alloc(&vp->v_uobj, uio->uio_offset, &bytelen, 333 UBC_READ); 334 error = uiomove(win, bytelen, uio); 335 ubc_release(win, 0); 336 if (error) 337 return (error); 338 } 339 340 return (0); 341 } 342 343 /* ARGSUSED */ 344 int 345 cd9660_ioctl(v) 346 void *v; 347 { 348 struct vop_ioctl_args /* { 349 struct vnode *a_vp; 350 u_long a_command; 351 caddr_t a_data; 352 int a_fflag; 353 struct ucred *a_cred; 354 struct proc *a_p; 355 } */ *ap = v; 356 daddr_t *block; 357 358 switch (ap->a_command) { 359 case FIBMAP: 360 block = (daddr_t *)ap->a_data; 361 362 return (VOP_BMAP(ap->a_vp, *block, NULL, block, 0)); 363 default: 364 return (ENOTTY); 365 } 366 } 367 368 /* ARGSUSED */ 369 int 370 cd9660_select(v) 371 void *v; 372 { 373 /* 374 * We should really check to see if I/O is possible. 375 */ 376 return (1); 377 } 378 379 /* 380 * Mmap a file 381 * 382 * NB Currently unsupported. 383 */ 384 /* ARGSUSED */ 385 int 386 cd9660_mmap(v) 387 void *v; 388 { 389 390 return (EINVAL); 391 } 392 393 /* 394 * Seek on a file 395 * 396 * Nothing to do, so just return. 397 */ 398 /* ARGSUSED */ 399 int 400 cd9660_seek(v) 401 void *v; 402 { 403 return (0); 404 } 405 406 int 407 iso_uiodir(idp,dp,off) 408 struct isoreaddir *idp; 409 struct dirent *dp; 410 off_t off; 411 { 412 int error; 413 414 dp->d_name[dp->d_namlen] = 0; 415 dp->d_reclen = DIRENT_SIZE(dp); 416 417 if (idp->uio->uio_resid < dp->d_reclen) { 418 idp->eofflag = 0; 419 return (-1); 420 } 421 422 if (idp->cookies) { 423 if (idp->ncookies <= 0) { 424 idp->eofflag = 0; 425 return (-1); 426 } 427 428 *idp->cookies++ = off; 429 --idp->ncookies; 430 } 431 432 if ((error = uiomove((caddr_t)dp, dp->d_reclen, idp->uio)) != 0) 433 return (error); 434 idp->uio_off = off; 435 return (0); 436 } 437 438 int 439 iso_shipdir(idp) 440 struct isoreaddir *idp; 441 { 442 struct dirent *dp; 443 int cl, sl, assoc; 444 int error; 445 char *cname, *sname; 446 447 cl = idp->current.d_namlen; 448 cname = idp->current.d_name; 449 450 if ((assoc = cl > 1 && *cname == ASSOCCHAR)) { 451 cl--; 452 cname++; 453 } 454 455 dp = &idp->saveent; 456 sname = dp->d_name; 457 if (!(sl = dp->d_namlen)) { 458 dp = &idp->assocent; 459 sname = dp->d_name + 1; 460 sl = dp->d_namlen - 1; 461 } 462 if (sl > 0) { 463 if (sl != cl 464 || bcmp(sname,cname,sl)) { 465 if (idp->assocent.d_namlen) { 466 error = iso_uiodir(idp, &idp->assocent, 467 idp->assocoff); 468 if (error) 469 return (error); 470 idp->assocent.d_namlen = 0; 471 } 472 if (idp->saveent.d_namlen) { 473 error = iso_uiodir(idp, &idp->saveent, 474 idp->saveoff); 475 if (error) 476 return (error); 477 idp->saveent.d_namlen = 0; 478 } 479 } 480 } 481 idp->current.d_reclen = DIRENT_SIZE(&idp->current); 482 if (assoc) { 483 idp->assocoff = idp->curroff; 484 bcopy(&idp->current,&idp->assocent,idp->current.d_reclen); 485 } else { 486 idp->saveoff = idp->curroff; 487 bcopy(&idp->current,&idp->saveent,idp->current.d_reclen); 488 } 489 return (0); 490 } 491 492 /* 493 * Vnode op for readdir 494 */ 495 int 496 cd9660_readdir(v) 497 void *v; 498 { 499 struct vop_readdir_args /* { 500 struct vnode *a_vp; 501 struct uio *a_uio; 502 struct ucred *a_cred; 503 int *a_eofflag; 504 u_long *a_cookies; 505 int a_ncookies; 506 } */ *ap = v; 507 register struct uio *uio = ap->a_uio; 508 struct isoreaddir *idp; 509 struct vnode *vdp = ap->a_vp; 510 struct iso_node *dp; 511 struct iso_mnt *imp; 512 struct buf *bp = NULL; 513 struct iso_directory_record *ep; 514 int entryoffsetinblock; 515 doff_t endsearch; 516 u_long bmask; 517 int error = 0; 518 int reclen; 519 u_short namelen; 520 int ncookies = 0; 521 u_long *cookies = NULL; 522 523 dp = VTOI(vdp); 524 imp = dp->i_mnt; 525 bmask = imp->im_bmask; 526 527 MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); 528 idp->saveent.d_namlen = idp->assocent.d_namlen = 0; 529 /* 530 * XXX 531 * Is it worth trying to figure out the type? 532 */ 533 idp->saveent.d_type = idp->assocent.d_type = idp->current.d_type = 534 DT_UNKNOWN; 535 idp->uio = uio; 536 if (ap->a_ncookies == NULL) { 537 idp->cookies = NULL; 538 } else { 539 /* 540 * Guess the number of cookies needed. 541 */ 542 ncookies = uio->uio_resid / 16; 543 MALLOC(cookies, u_long *, ncookies * sizeof(u_long), M_TEMP, 544 M_WAITOK); 545 idp->cookies = cookies; 546 idp->ncookies = ncookies; 547 } 548 idp->eofflag = 1; 549 idp->curroff = uio->uio_offset; 550 551 if ((entryoffsetinblock = idp->curroff & bmask) && 552 (error = cd9660_bufatoff(dp, (off_t)idp->curroff, NULL, &bp))) { 553 FREE(idp, M_TEMP); 554 return (error); 555 } 556 endsearch = dp->i_size; 557 558 while (idp->curroff < endsearch) { 559 /* 560 * If offset is on a block boundary, 561 * read the next directory block. 562 * Release previous if it exists. 563 */ 564 if ((idp->curroff & bmask) == 0) { 565 if (bp != NULL) 566 brelse(bp); 567 error = cd9660_bufatoff(dp, (off_t)idp->curroff, 568 NULL, &bp); 569 if (error) 570 break; 571 entryoffsetinblock = 0; 572 } 573 /* 574 * Get pointer to next entry. 575 */ 576 ep = (struct iso_directory_record *) 577 ((char *)bp->b_data + entryoffsetinblock); 578 579 reclen = isonum_711(ep->length); 580 if (reclen == 0) { 581 /* skip to next block, if any */ 582 idp->curroff = 583 (idp->curroff & ~bmask) + imp->logical_block_size; 584 continue; 585 } 586 587 if (reclen < ISO_DIRECTORY_RECORD_SIZE) { 588 error = EINVAL; 589 /* illegal entry, stop */ 590 break; 591 } 592 593 if (entryoffsetinblock + reclen > imp->logical_block_size) { 594 error = EINVAL; 595 /* illegal directory, so stop looking */ 596 break; 597 } 598 599 idp->current.d_namlen = isonum_711(ep->name_len); 600 601 if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) { 602 error = EINVAL; 603 /* illegal entry, stop */ 604 break; 605 } 606 607 if (isonum_711(ep->flags)&2) 608 idp->current.d_fileno = isodirino(ep, imp); 609 else 610 idp->current.d_fileno = dbtob(bp->b_blkno) + 611 entryoffsetinblock; 612 613 idp->curroff += reclen; 614 615 switch (imp->iso_ftype) { 616 case ISO_FTYPE_RRIP: 617 cd9660_rrip_getname(ep,idp->current.d_name, &namelen, 618 &idp->current.d_fileno,imp); 619 idp->current.d_namlen = (u_char)namelen; 620 if (idp->current.d_namlen) 621 error = iso_uiodir(idp,&idp->current,idp->curroff); 622 break; 623 default: /* ISO_FTYPE_DEFAULT || ISO_FTYPE_9660 */ 624 strcpy(idp->current.d_name,".."); 625 if (idp->current.d_namlen == 1 && ep->name[0] == 0) { 626 idp->current.d_namlen = 1; 627 error = iso_uiodir(idp,&idp->current,idp->curroff); 628 } else if (idp->current.d_namlen == 1 && 629 ep->name[0] == 1) { 630 idp->current.d_namlen = 2; 631 error = iso_uiodir(idp,&idp->current,idp->curroff); 632 } else { 633 isofntrans(ep->name,idp->current.d_namlen, 634 idp->current.d_name, &namelen, 635 imp->iso_ftype == ISO_FTYPE_9660, 636 isonum_711(ep->flags) & 4, 637 imp->joliet_level); 638 idp->current.d_namlen = (u_char)namelen; 639 if (imp->iso_ftype == ISO_FTYPE_DEFAULT) 640 error = iso_shipdir(idp); 641 else 642 error = iso_uiodir(idp,&idp->current,idp->curroff); 643 } 644 } 645 if (error) 646 break; 647 648 entryoffsetinblock += reclen; 649 } 650 651 if (!error && imp->iso_ftype == ISO_FTYPE_DEFAULT) { 652 idp->current.d_namlen = 0; 653 error = iso_shipdir(idp); 654 } 655 if (error < 0) 656 error = 0; 657 658 if (ap->a_ncookies != NULL) { 659 if (error) 660 free(cookies, M_TEMP); 661 else { 662 /* 663 * Work out the number of cookies actually used. 664 */ 665 *ap->a_ncookies = ncookies - idp->ncookies; 666 *ap->a_cookies = cookies; 667 } 668 } 669 670 if (bp) 671 brelse (bp); 672 673 uio->uio_offset = idp->uio_off; 674 *ap->a_eofflag = idp->eofflag; 675 676 FREE(idp, M_TEMP); 677 678 return (error); 679 } 680 681 /* 682 * Return target name of a symbolic link 683 * Shouldn't we get the parent vnode and read the data from there? 684 * This could eventually result in deadlocks in cd9660_lookup. 685 * But otherwise the block read here is in the block buffer two times. 686 */ 687 typedef struct iso_directory_record ISODIR; 688 typedef struct iso_node ISONODE; 689 typedef struct iso_mnt ISOMNT; 690 int 691 cd9660_readlink(v) 692 void *v; 693 { 694 struct vop_readlink_args /* { 695 struct vnode *a_vp; 696 struct uio *a_uio; 697 struct ucred *a_cred; 698 } */ *ap = v; 699 ISONODE *ip; 700 ISODIR *dirp; 701 ISOMNT *imp; 702 struct buf *bp; 703 struct uio *uio; 704 u_short symlen; 705 int error; 706 char *symname; 707 708 ip = VTOI(ap->a_vp); 709 imp = ip->i_mnt; 710 uio = ap->a_uio; 711 712 if (imp->iso_ftype != ISO_FTYPE_RRIP) 713 return (EINVAL); 714 715 /* 716 * Get parents directory record block that this inode included. 717 */ 718 error = bread(imp->im_devvp, 719 (ip->i_number >> imp->im_bshift) << 720 (imp->im_bshift - DEV_BSHIFT), 721 imp->logical_block_size, NOCRED, &bp); 722 if (error) { 723 brelse(bp); 724 return (EINVAL); 725 } 726 727 /* 728 * Setup the directory pointer for this inode 729 */ 730 dirp = (ISODIR *)(bp->b_data + (ip->i_number & imp->im_bmask)); 731 732 /* 733 * Just make sure, we have a right one.... 734 * 1: Check not cross boundary on block 735 */ 736 if ((ip->i_number & imp->im_bmask) + isonum_711(dirp->length) 737 > imp->logical_block_size) { 738 brelse(bp); 739 return (EINVAL); 740 } 741 742 /* 743 * Now get a buffer 744 * Abuse a namei buffer for now. 745 */ 746 if (uio->uio_segflg == UIO_SYSSPACE) 747 symname = uio->uio_iov->iov_base; 748 else 749 MALLOC(symname, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 750 751 /* 752 * Ok, we just gathering a symbolic name in SL record. 753 */ 754 if (cd9660_rrip_getsymname(dirp, symname, &symlen, imp) == 0) { 755 if (uio->uio_segflg != UIO_SYSSPACE) 756 FREE(symname, M_NAMEI); 757 brelse(bp); 758 return (EINVAL); 759 } 760 /* 761 * Don't forget before you leave from home ;-) 762 */ 763 brelse(bp); 764 765 /* 766 * return with the symbolic name to caller's. 767 */ 768 if (uio->uio_segflg != UIO_SYSSPACE) { 769 error = uiomove(symname, symlen, uio); 770 FREE(symname, M_NAMEI); 771 return (error); 772 } 773 uio->uio_resid -= symlen; 774 uio->uio_iov->iov_base += symlen; 775 uio->uio_iov->iov_len -= symlen; 776 return (0); 777 } 778 779 int 780 cd9660_link(v) 781 void *v; 782 { 783 struct vop_link_args /* { 784 struct vnode *a_dvp; 785 struct vnode *a_vp; 786 struct componentname *a_cnp; 787 } */ *ap = v; 788 789 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 790 vput(ap->a_dvp); 791 return (EROFS); 792 } 793 794 int 795 cd9660_symlink(v) 796 void *v; 797 { 798 struct vop_symlink_args /* { 799 struct vnode *a_dvp; 800 struct vnode **a_vpp; 801 struct componentname *a_cnp; 802 struct vattr *a_vap; 803 char *a_target; 804 } */ *ap = v; 805 806 VOP_ABORTOP(ap->a_dvp, ap->a_cnp); 807 vput(ap->a_dvp); 808 return (EROFS); 809 } 810 811 /* 812 * Lock an inode. 813 */ 814 int 815 cd9660_lock(v) 816 void *v; 817 { 818 struct vop_lock_args /* { 819 struct vnode *a_vp; 820 } */ *ap = v; 821 struct vnode *vp = ap->a_vp; 822 823 return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags, &vp->v_interlock, 824 ap->a_p)); 825 } 826 827 /* 828 * Unlock an inode. 829 */ 830 int 831 cd9660_unlock(v) 832 void *v; 833 { 834 struct vop_unlock_args /* { 835 struct vnode *a_vp; 836 } */ *ap = v; 837 struct vnode *vp = ap->a_vp; 838 839 return (lockmgr(&VTOI(vp)->i_lock, ap->a_flags | LK_RELEASE, 840 &vp->v_interlock, ap->a_p)); 841 } 842 843 /* 844 * Calculate the logical to physical mapping if not done already, 845 * then call the device strategy routine. 846 */ 847 int 848 cd9660_strategy(v) 849 void *v; 850 { 851 struct vop_strategy_args /* { 852 struct buf *a_bp; 853 } */ *ap = v; 854 register struct buf *bp = ap->a_bp; 855 register struct vnode *vp = bp->b_vp; 856 register struct iso_node *ip; 857 int error; 858 859 ip = VTOI(vp); 860 if (vp->v_type == VBLK || vp->v_type == VCHR) 861 panic("cd9660_strategy: spec"); 862 if (bp->b_blkno == bp->b_lblkno) { 863 error = VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL); 864 if (error) { 865 bp->b_error = error; 866 bp->b_flags |= B_ERROR; 867 biodone(bp); 868 return (error); 869 } 870 if ((long)bp->b_blkno == -1) 871 clrbuf(bp); 872 } 873 if ((long)bp->b_blkno == -1) { 874 biodone(bp); 875 return (0); 876 } 877 vp = ip->i_devvp; 878 bp->b_dev = vp->v_rdev; 879 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap); 880 return (0); 881 } 882 883 /* 884 * Print out the contents of an inode. 885 */ 886 /*ARGSUSED*/ 887 int 888 cd9660_print(v) 889 void *v; 890 { 891 printf("tag VT_ISOFS, isofs vnode\n"); 892 return (0); 893 } 894 895 /* 896 * Check for a locked inode. 897 */ 898 int 899 cd9660_islocked(v) 900 void *v; 901 { 902 struct vop_islocked_args /* { 903 struct vnode *a_vp; 904 } */ *ap = v; 905 906 return (lockstatus(&VTOI(ap->a_vp)->i_lock)); 907 } 908 909 /* 910 * Return POSIX pathconf information applicable to cd9660 filesystems. 911 */ 912 int 913 cd9660_pathconf(v) 914 void *v; 915 { 916 struct vop_pathconf_args /* { 917 struct vnode *a_vp; 918 int a_name; 919 register_t *a_retval; 920 } */ *ap = v; 921 switch (ap->a_name) { 922 case _PC_LINK_MAX: 923 *ap->a_retval = 1; 924 return (0); 925 case _PC_NAME_MAX: 926 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 927 *ap->a_retval = NAME_MAX; 928 else 929 *ap->a_retval = 37; 930 return (0); 931 case _PC_PATH_MAX: 932 *ap->a_retval = PATH_MAX; 933 return (0); 934 case _PC_PIPE_BUF: 935 *ap->a_retval = PIPE_BUF; 936 return (0); 937 case _PC_CHOWN_RESTRICTED: 938 *ap->a_retval = 1; 939 return (0); 940 case _PC_NO_TRUNC: 941 *ap->a_retval = 1; 942 return (0); 943 default: 944 return (EINVAL); 945 } 946 /* NOTREACHED */ 947 } 948 949 /* 950 * Global vfs data structures for isofs 951 */ 952 #define cd9660_create eopnotsupp 953 #define cd9660_mknod eopnotsupp 954 #define cd9660_write eopnotsupp 955 #ifdef NFSSERVER 956 int lease_check __P((void *)); 957 #define cd9660_lease_check lease_check 958 #else 959 #define cd9660_lease_check nullop 960 #endif 961 #define cd9660_fsync nullop 962 #define cd9660_remove eopnotsupp 963 #define cd9660_rename eopnotsupp 964 #define cd9660_mkdir eopnotsupp 965 #define cd9660_rmdir eopnotsupp 966 #define cd9660_advlock eopnotsupp 967 #define cd9660_valloc eopnotsupp 968 #define cd9660_vfree eopnotsupp 969 #define cd9660_truncate eopnotsupp 970 #define cd9660_update eopnotsupp 971 #define cd9660_bwrite eopnotsupp 972 #define cd9660_revoke vop_generic_revoke 973 974 /* 975 * Global vfs data structures for cd9660 976 */ 977 int (**cd9660_vnodeop_p) __P((void *)); 978 struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 979 { &vop_default_desc, vn_default_error }, 980 { &vop_lookup_desc, cd9660_lookup }, /* lookup */ 981 { &vop_create_desc, cd9660_create }, /* create */ 982 { &vop_mknod_desc, cd9660_mknod }, /* mknod */ 983 { &vop_open_desc, cd9660_open }, /* open */ 984 { &vop_close_desc, cd9660_close }, /* close */ 985 { &vop_access_desc, cd9660_access }, /* access */ 986 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 987 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 988 { &vop_read_desc, cd9660_read }, /* read */ 989 { &vop_write_desc, cd9660_write }, /* write */ 990 { &vop_lease_desc, cd9660_lease_check },/* lease */ 991 { &vop_ioctl_desc, cd9660_ioctl }, /* ioctl */ 992 { &vop_select_desc, cd9660_select }, /* select */ 993 { &vop_revoke_desc, cd9660_revoke }, /* revoke */ 994 { &vop_fsync_desc, cd9660_fsync }, /* fsync */ 995 { &vop_remove_desc, cd9660_remove }, /* remove */ 996 { &vop_link_desc, cd9660_link }, /* link */ 997 { &vop_rename_desc, cd9660_rename }, /* rename */ 998 { &vop_mkdir_desc, cd9660_mkdir }, /* mkdir */ 999 { &vop_rmdir_desc, cd9660_rmdir }, /* rmdir */ 1000 { &vop_symlink_desc, cd9660_symlink }, /* symlink */ 1001 { &vop_readdir_desc, cd9660_readdir }, /* readdir */ 1002 { &vop_readlink_desc, cd9660_readlink },/* readlink */ 1003 { &vop_abortop_desc, vop_generic_abortop }, /* abortop */ 1004 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1005 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1006 { &vop_lock_desc, cd9660_lock }, /* lock */ 1007 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1008 { &vop_bmap_desc, cd9660_bmap }, /* bmap */ 1009 { &vop_strategy_desc, cd9660_strategy },/* strategy */ 1010 { &vop_print_desc, cd9660_print }, /* print */ 1011 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1012 { &vop_pathconf_desc, cd9660_pathconf },/* pathconf */ 1013 { &vop_advlock_desc, cd9660_advlock }, /* advlock */ 1014 { &vop_bwrite_desc, vop_generic_bwrite }, 1015 { &vop_getpages_desc, genfs_getpages }, 1016 { &vop_mmap_desc, cd9660_mmap }, 1017 { NULL, NULL } 1018 }; 1019 struct vnodeopv_desc cd9660_vnodeop_opv_desc = 1020 { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 1021 1022 /* 1023 * Special device vnode ops 1024 */ 1025 int (**cd9660_specop_p) __P((void *)); 1026 struct vnodeopv_entry_desc cd9660_specop_entries[] = { 1027 { &vop_default_desc, vn_default_error }, 1028 { &vop_lookup_desc, spec_lookup }, /* lookup */ 1029 { &vop_create_desc, spec_create }, /* create */ 1030 { &vop_mknod_desc, spec_mknod }, /* mknod */ 1031 { &vop_open_desc, spec_open }, /* open */ 1032 { &vop_close_desc, spec_close }, /* close */ 1033 { &vop_access_desc, cd9660_access }, /* access */ 1034 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1035 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1036 { &vop_read_desc, spec_read }, /* read */ 1037 { &vop_write_desc, spec_write }, /* write */ 1038 { &vop_lease_desc, spec_lease_check }, /* lease */ 1039 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 1040 { &vop_select_desc, spec_select }, /* select */ 1041 { &vop_revoke_desc, spec_revoke }, /* revoke */ 1042 { &vop_fsync_desc, spec_fsync }, /* fsync */ 1043 { &vop_remove_desc, spec_remove }, /* remove */ 1044 { &vop_link_desc, spec_link }, /* link */ 1045 { &vop_rename_desc, spec_rename }, /* rename */ 1046 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 1047 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 1048 { &vop_symlink_desc, spec_symlink }, /* symlink */ 1049 { &vop_readdir_desc, spec_readdir }, /* readdir */ 1050 { &vop_readlink_desc, spec_readlink }, /* readlink */ 1051 { &vop_abortop_desc, spec_abortop }, /* abortop */ 1052 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1053 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1054 { &vop_lock_desc, cd9660_lock }, /* lock */ 1055 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1056 { &vop_bmap_desc, spec_bmap }, /* bmap */ 1057 { &vop_strategy_desc, spec_strategy }, /* strategy */ 1058 { &vop_print_desc, cd9660_print }, /* print */ 1059 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1060 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 1061 { &vop_advlock_desc, spec_advlock }, /* advlock */ 1062 { &vop_bwrite_desc, vop_generic_bwrite }, 1063 { &vop_mmap_desc, spec_mmap }, 1064 { NULL, NULL } 1065 }; 1066 struct vnodeopv_desc cd9660_specop_opv_desc = 1067 { &cd9660_specop_p, cd9660_specop_entries }; 1068 1069 #ifdef FIFO 1070 int (**cd9660_fifoop_p) __P((void *)); 1071 struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 1072 { &vop_default_desc, vn_default_error }, 1073 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 1074 { &vop_create_desc, fifo_create }, /* create */ 1075 { &vop_mknod_desc, fifo_mknod }, /* mknod */ 1076 { &vop_open_desc, fifo_open }, /* open */ 1077 { &vop_close_desc, fifo_close }, /* close */ 1078 { &vop_access_desc, cd9660_access }, /* access */ 1079 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1080 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1081 { &vop_read_desc, fifo_read }, /* read */ 1082 { &vop_write_desc, fifo_write }, /* write */ 1083 { &vop_lease_desc, fifo_lease_check }, /* lease */ 1084 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 1085 { &vop_select_desc, fifo_select }, /* select */ 1086 { &vop_revoke_desc, fifo_revoke }, /* revoke */ 1087 { &vop_fsync_desc, fifo_fsync }, /* fsync */ 1088 { &vop_remove_desc, fifo_remove }, /* remove */ 1089 { &vop_link_desc, fifo_link } , /* link */ 1090 { &vop_rename_desc, fifo_rename }, /* rename */ 1091 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 1092 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 1093 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 1094 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 1095 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 1096 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 1097 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1098 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1099 { &vop_lock_desc, cd9660_lock }, /* lock */ 1100 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1101 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 1102 { &vop_strategy_desc, fifo_strategy }, /* strategy */ 1103 { &vop_print_desc, cd9660_print }, /* print */ 1104 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1105 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 1106 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 1107 { &vop_bwrite_desc, vop_generic_bwrite }, 1108 { &vop_mmap_desc, fifo_mmap }, 1109 { NULL, NULL } 1110 }; 1111 struct vnodeopv_desc cd9660_fifoop_opv_desc = 1112 { &cd9660_fifoop_p, cd9660_fifoop_entries }; 1113 #endif /* FIFO */ 1114