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