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.17 (Berkeley) 03/30/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 } */ *ap; 808 { 809 register struct vnode *vp = ap->a_vp; 810 register struct iso_node *ip; 811 struct proc *p = curproc; /* XXX */ 812 813 start: 814 while (vp->v_flag & VXLOCK) { 815 vp->v_flag |= VXWANT; 816 sleep((caddr_t)vp, PINOD); 817 } 818 if (vp->v_tag == VT_NON) 819 return (ENOENT); 820 ip = VTOI(vp); 821 if (ip->i_flag & IN_LOCKED) { 822 ip->i_flag |= IN_WANTED; 823 #ifdef DIAGNOSTIC 824 if (p) { 825 if (p->p_pid == ip->i_lockholder) 826 panic("locking against myself"); 827 ip->i_lockwaiter = p->p_pid; 828 } else 829 ip->i_lockwaiter = -1; 830 #endif 831 (void) sleep((caddr_t)ip, PINOD); 832 } 833 #ifdef DIAGNOSTIC 834 ip->i_lockwaiter = 0; 835 if (ip->i_lockholder != 0) 836 panic("lockholder (%d) != 0", ip->i_lockholder); 837 if (p && p->p_pid == 0) 838 printf("locking by process 0\n"); 839 if (p) 840 ip->i_lockholder = p->p_pid; 841 else 842 ip->i_lockholder = -1; 843 #endif 844 ip->i_flag |= IN_LOCKED; 845 return (0); 846 } 847 848 /* 849 * Unlock an inode. 850 */ 851 int 852 cd9660_unlock(ap) 853 struct vop_unlock_args /* { 854 struct vnode *a_vp; 855 } */ *ap; 856 { 857 register struct iso_node *ip = VTOI(ap->a_vp); 858 struct proc *p = curproc; /* XXX */ 859 860 #ifdef DIAGNOSTIC 861 if ((ip->i_flag & IN_LOCKED) == 0) { 862 vprint("ufs_unlock: unlocked inode", ap->a_vp); 863 panic("ufs_unlock NOT LOCKED"); 864 } 865 if (p && p->p_pid != ip->i_lockholder && p->p_pid > -1 && 866 ip->i_lockholder > -1/* && lockcount++ < 100*/) 867 panic("unlocker (%d) != lock holder (%d)", 868 p->p_pid, ip->i_lockholder); 869 ip->i_lockholder = 0; 870 #endif 871 ip->i_flag &= ~IN_LOCKED; 872 if (ip->i_flag & IN_WANTED) { 873 ip->i_flag &= ~IN_WANTED; 874 wakeup((caddr_t)ip); 875 } 876 return (0); 877 } 878 879 /* 880 * Calculate the logical to physical mapping if not done already, 881 * then call the device strategy routine. 882 */ 883 int 884 cd9660_strategy(ap) 885 struct vop_strategy_args /* { 886 struct buf *a_bp; 887 } */ *ap; 888 { 889 register struct buf *bp = ap->a_bp; 890 register struct vnode *vp = bp->b_vp; 891 register struct iso_node *ip; 892 int error; 893 894 ip = VTOI(vp); 895 if (vp->v_type == VBLK || vp->v_type == VCHR) 896 panic("cd9660_strategy: spec"); 897 if (bp->b_blkno == bp->b_lblkno) { 898 if (error = 899 VOP_BMAP(vp, bp->b_lblkno, NULL, &bp->b_blkno, NULL)) { 900 bp->b_error = error; 901 bp->b_flags |= B_ERROR; 902 biodone(bp); 903 return (error); 904 } 905 if ((long)bp->b_blkno == -1) 906 clrbuf(bp); 907 } 908 if ((long)bp->b_blkno == -1) { 909 biodone(bp); 910 return (0); 911 } 912 vp = ip->i_devvp; 913 bp->b_dev = vp->v_rdev; 914 VOCALL (vp->v_op, VOFFSET(vop_strategy), ap); 915 return (0); 916 } 917 918 /* 919 * Print out the contents of an inode. 920 */ 921 int 922 cd9660_print(ap) 923 struct vop_print_args /* { 924 struct vnode *a_vp; 925 } */ *ap; 926 { 927 928 printf("tag VT_ISOFS, isofs vnode\n"); 929 return (0); 930 } 931 932 /* 933 * Check for a locked inode. 934 */ 935 int 936 cd9660_islocked(ap) 937 struct vop_islocked_args /* { 938 struct vnode *a_vp; 939 } */ *ap; 940 { 941 942 if (VTOI(ap->a_vp)->i_flag & IN_LOCKED) 943 return (1); 944 return (0); 945 } 946 947 /* 948 * Return POSIX pathconf information applicable to cd9660 filesystems. 949 */ 950 int 951 cd9660_pathconf(ap) 952 struct vop_pathconf_args /* { 953 struct vnode *a_vp; 954 int a_name; 955 register_t *a_retval; 956 } */ *ap; 957 { 958 959 switch (ap->a_name) { 960 case _PC_LINK_MAX: 961 *ap->a_retval = 1; 962 return (0); 963 case _PC_NAME_MAX: 964 if (VTOI(ap->a_vp)->i_mnt->iso_ftype == ISO_FTYPE_RRIP) 965 *ap->a_retval = NAME_MAX; 966 else 967 *ap->a_retval = 37; 968 return (0); 969 case _PC_PATH_MAX: 970 *ap->a_retval = PATH_MAX; 971 return (0); 972 case _PC_PIPE_BUF: 973 *ap->a_retval = PIPE_BUF; 974 return (0); 975 case _PC_CHOWN_RESTRICTED: 976 *ap->a_retval = 1; 977 return (0); 978 case _PC_NO_TRUNC: 979 *ap->a_retval = 1; 980 return (0); 981 default: 982 return (EINVAL); 983 } 984 /* NOTREACHED */ 985 } 986 987 /* 988 * Global vfs data structures for isofs 989 */ 990 #define cd9660_create \ 991 ((int (*) __P((struct vop_create_args *)))eopnotsupp) 992 #define cd9660_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp) 993 #define cd9660_setattr \ 994 ((int (*) __P((struct vop_setattr_args *)))eopnotsupp) 995 #define cd9660_write ((int (*) __P((struct vop_write_args *)))eopnotsupp) 996 #ifdef NFS 997 int lease_check __P((struct vop_lease_args *)); 998 #define cd9660_lease_check lease_check 999 #else 1000 #define cd9660_lease_check ((int (*) __P((struct vop_lease_args *)))nullop) 1001 #endif 1002 #define cd9660_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 1003 #define cd9660_remove \ 1004 ((int (*) __P((struct vop_remove_args *)))eopnotsupp) 1005 #define cd9660_link ((int (*) __P((struct vop_link_args *)))eopnotsupp) 1006 #define cd9660_rename \ 1007 ((int (*) __P((struct vop_rename_args *)))eopnotsupp) 1008 #define cd9660_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp) 1009 #define cd9660_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp) 1010 #define cd9660_symlink \ 1011 ((int (*) __P((struct vop_symlink_args *)))eopnotsupp) 1012 #define cd9660_advlock \ 1013 ((int (*) __P((struct vop_advlock_args *)))eopnotsupp) 1014 #define cd9660_valloc ((int(*) __P(( \ 1015 struct vnode *pvp, \ 1016 int mode, \ 1017 struct ucred *cred, \ 1018 struct vnode **vpp))) eopnotsupp) 1019 #define cd9660_vfree ((int (*) __P((struct vop_vfree_args *)))eopnotsupp) 1020 #define cd9660_truncate \ 1021 ((int (*) __P((struct vop_truncate_args *)))eopnotsupp) 1022 #define cd9660_update \ 1023 ((int (*) __P((struct vop_update_args *)))eopnotsupp) 1024 #define cd9660_bwrite \ 1025 ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp) 1026 1027 /* 1028 * Global vfs data structures for cd9660 1029 */ 1030 int (**cd9660_vnodeop_p)(); 1031 struct vnodeopv_entry_desc cd9660_vnodeop_entries[] = { 1032 { &vop_default_desc, vn_default_error }, 1033 { &vop_lookup_desc, cd9660_lookup }, /* lookup */ 1034 { &vop_create_desc, cd9660_create }, /* create */ 1035 { &vop_mknod_desc, cd9660_mknod }, /* mknod */ 1036 { &vop_open_desc, cd9660_open }, /* open */ 1037 { &vop_close_desc, cd9660_close }, /* close */ 1038 { &vop_access_desc, cd9660_access }, /* access */ 1039 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1040 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1041 { &vop_read_desc, cd9660_read }, /* read */ 1042 { &vop_write_desc, cd9660_write }, /* write */ 1043 { &vop_lease_desc, cd9660_lease_check },/* lease */ 1044 { &vop_ioctl_desc, cd9660_ioctl }, /* ioctl */ 1045 { &vop_select_desc, cd9660_select }, /* select */ 1046 { &vop_revoke_desc, cd9660_revoke }, /* revoke */ 1047 { &vop_mmap_desc, cd9660_mmap }, /* mmap */ 1048 { &vop_fsync_desc, cd9660_fsync }, /* fsync */ 1049 { &vop_seek_desc, cd9660_seek }, /* seek */ 1050 { &vop_remove_desc, cd9660_remove }, /* remove */ 1051 { &vop_link_desc, cd9660_link }, /* link */ 1052 { &vop_rename_desc, cd9660_rename }, /* rename */ 1053 { &vop_mkdir_desc, cd9660_mkdir }, /* mkdir */ 1054 { &vop_rmdir_desc, cd9660_rmdir }, /* rmdir */ 1055 { &vop_symlink_desc, cd9660_symlink }, /* symlink */ 1056 { &vop_readdir_desc, cd9660_readdir }, /* readdir */ 1057 { &vop_readlink_desc, cd9660_readlink },/* readlink */ 1058 { &vop_abortop_desc, cd9660_abortop }, /* abortop */ 1059 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1060 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1061 { &vop_lock_desc, cd9660_lock }, /* lock */ 1062 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1063 { &vop_bmap_desc, cd9660_bmap }, /* bmap */ 1064 { &vop_strategy_desc, cd9660_strategy },/* strategy */ 1065 { &vop_print_desc, cd9660_print }, /* print */ 1066 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1067 { &vop_pathconf_desc, cd9660_pathconf },/* pathconf */ 1068 { &vop_advlock_desc, cd9660_advlock }, /* advlock */ 1069 { &vop_blkatoff_desc, cd9660_blkatoff },/* blkatoff */ 1070 { &vop_valloc_desc, cd9660_valloc }, /* valloc */ 1071 { &vop_vfree_desc, cd9660_vfree }, /* vfree */ 1072 { &vop_truncate_desc, cd9660_truncate },/* truncate */ 1073 { &vop_update_desc, cd9660_update }, /* update */ 1074 { &vop_bwrite_desc, vn_bwrite }, 1075 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1076 }; 1077 struct vnodeopv_desc cd9660_vnodeop_opv_desc = 1078 { &cd9660_vnodeop_p, cd9660_vnodeop_entries }; 1079 1080 /* 1081 * Special device vnode ops 1082 */ 1083 int (**cd9660_specop_p)(); 1084 struct vnodeopv_entry_desc cd9660_specop_entries[] = { 1085 { &vop_default_desc, vn_default_error }, 1086 { &vop_lookup_desc, spec_lookup }, /* lookup */ 1087 { &vop_create_desc, spec_create }, /* create */ 1088 { &vop_mknod_desc, spec_mknod }, /* mknod */ 1089 { &vop_open_desc, spec_open }, /* open */ 1090 { &vop_close_desc, spec_close }, /* close */ 1091 { &vop_access_desc, cd9660_access }, /* access */ 1092 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1093 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1094 { &vop_read_desc, spec_read }, /* read */ 1095 { &vop_write_desc, spec_write }, /* write */ 1096 { &vop_lease_desc, spec_lease_check }, /* lease */ 1097 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 1098 { &vop_select_desc, spec_select }, /* select */ 1099 { &vop_revoke_desc, spec_revoke }, /* revoke */ 1100 { &vop_mmap_desc, spec_mmap }, /* mmap */ 1101 { &vop_fsync_desc, spec_fsync }, /* fsync */ 1102 { &vop_seek_desc, spec_seek }, /* seek */ 1103 { &vop_remove_desc, spec_remove }, /* remove */ 1104 { &vop_link_desc, spec_link }, /* link */ 1105 { &vop_rename_desc, spec_rename }, /* rename */ 1106 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 1107 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 1108 { &vop_symlink_desc, spec_symlink }, /* symlink */ 1109 { &vop_readdir_desc, spec_readdir }, /* readdir */ 1110 { &vop_readlink_desc, spec_readlink }, /* readlink */ 1111 { &vop_abortop_desc, spec_abortop }, /* abortop */ 1112 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1113 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1114 { &vop_lock_desc, cd9660_lock }, /* lock */ 1115 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1116 { &vop_bmap_desc, spec_bmap }, /* bmap */ 1117 { &vop_strategy_desc, spec_strategy }, /* strategy */ 1118 { &vop_print_desc, cd9660_print }, /* print */ 1119 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1120 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 1121 { &vop_advlock_desc, spec_advlock }, /* advlock */ 1122 { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 1123 { &vop_valloc_desc, spec_valloc }, /* valloc */ 1124 { &vop_vfree_desc, spec_vfree }, /* vfree */ 1125 { &vop_truncate_desc, spec_truncate }, /* truncate */ 1126 { &vop_update_desc, cd9660_update }, /* update */ 1127 { &vop_bwrite_desc, vn_bwrite }, 1128 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1129 }; 1130 struct vnodeopv_desc cd9660_specop_opv_desc = 1131 { &cd9660_specop_p, cd9660_specop_entries }; 1132 1133 #ifdef FIFO 1134 int (**cd9660_fifoop_p)(); 1135 struct vnodeopv_entry_desc cd9660_fifoop_entries[] = { 1136 { &vop_default_desc, vn_default_error }, 1137 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 1138 { &vop_create_desc, fifo_create }, /* create */ 1139 { &vop_mknod_desc, fifo_mknod }, /* mknod */ 1140 { &vop_open_desc, fifo_open }, /* open */ 1141 { &vop_close_desc, fifo_close }, /* close */ 1142 { &vop_access_desc, cd9660_access }, /* access */ 1143 { &vop_getattr_desc, cd9660_getattr }, /* getattr */ 1144 { &vop_setattr_desc, cd9660_setattr }, /* setattr */ 1145 { &vop_read_desc, fifo_read }, /* read */ 1146 { &vop_write_desc, fifo_write }, /* write */ 1147 { &vop_lease_desc, fifo_lease_check }, /* lease */ 1148 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 1149 { &vop_select_desc, fifo_select }, /* select */ 1150 { &vop_revoke_desc, fifo_revoke }, /* revoke */ 1151 { &vop_mmap_desc, fifo_mmap }, /* mmap */ 1152 { &vop_fsync_desc, fifo_fsync }, /* fsync */ 1153 { &vop_seek_desc, fifo_seek }, /* seek */ 1154 { &vop_remove_desc, fifo_remove }, /* remove */ 1155 { &vop_link_desc, fifo_link } , /* link */ 1156 { &vop_rename_desc, fifo_rename }, /* rename */ 1157 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 1158 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 1159 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 1160 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 1161 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 1162 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 1163 { &vop_inactive_desc, cd9660_inactive },/* inactive */ 1164 { &vop_reclaim_desc, cd9660_reclaim }, /* reclaim */ 1165 { &vop_lock_desc, cd9660_lock }, /* lock */ 1166 { &vop_unlock_desc, cd9660_unlock }, /* unlock */ 1167 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 1168 { &vop_strategy_desc, fifo_strategy }, /* strategy */ 1169 { &vop_print_desc, cd9660_print }, /* print */ 1170 { &vop_islocked_desc, cd9660_islocked },/* islocked */ 1171 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 1172 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 1173 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 1174 { &vop_valloc_desc, fifo_valloc }, /* valloc */ 1175 { &vop_vfree_desc, fifo_vfree }, /* vfree */ 1176 { &vop_truncate_desc, fifo_truncate }, /* truncate */ 1177 { &vop_update_desc, cd9660_update }, /* update */ 1178 { &vop_bwrite_desc, vn_bwrite }, 1179 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 1180 }; 1181 struct vnodeopv_desc cd9660_fifoop_opv_desc = 1182 { &cd9660_fifoop_p, cd9660_fifoop_entries }; 1183 #endif /* FIFO */ 1184