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