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