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