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