1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * All rights reserved. 5 * 6 * This code is derived from software donated to Berkeley by 7 * Jan-Simon Pendry. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)fdesc_vnops.c 8.7 (Berkeley) 01/05/94 12 * 13 * $Id: fdesc_vnops.c,v 1.12 1993/04/06 16:17:17 jsp Exp $ 14 */ 15 16 /* 17 * /dev/fd Filesystem 18 */ 19 20 #include <sys/param.h> 21 #include <sys/systm.h> 22 #include <sys/types.h> 23 #include <sys/time.h> 24 #include <sys/proc.h> 25 #include <sys/kernel.h> /* boottime */ 26 #include <sys/resourcevar.h> 27 #include <sys/filedesc.h> 28 #include <sys/vnode.h> 29 #include <sys/malloc.h> 30 #include <sys/file.h> 31 #include <sys/stat.h> 32 #include <sys/mount.h> 33 #include <sys/namei.h> 34 #include <sys/buf.h> 35 #include <sys/dirent.h> 36 #include <miscfs/fdesc/fdesc.h> 37 38 #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL) 39 40 #define FDL_WANT 0x01 41 #define FDL_LOCKED 0x02 42 static int fdcache_lock; 43 44 dev_t devctty; 45 46 #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1) 47 FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2 48 #endif 49 50 #define NFDCACHE 3 51 #define FD_NHASH(ix) ((ix) & NFDCACHE) 52 53 /* 54 * Cache head 55 */ 56 struct fdcache { 57 struct fdescnode *fc_forw; 58 struct fdescnode *fc_back; 59 }; 60 61 static struct fdcache fdcache[NFDCACHE]; 62 63 /* 64 * Initialise cache headers 65 */ 66 fdesc_init() 67 { 68 struct fdcache *fc; 69 70 devctty = makedev(nchrdev, 0); 71 72 for (fc = fdcache; fc < fdcache + NFDCACHE; fc++) 73 fc->fc_forw = fc->fc_back = (struct fdescnode *) fc; 74 } 75 76 /* 77 * Compute hash list for given target vnode 78 */ 79 static struct fdcache * 80 fdesc_hash(ix) 81 int ix; 82 { 83 84 return (&fdcache[FD_NHASH(ix)]); 85 } 86 87 int 88 fdesc_allocvp(ftype, ix, mp, vpp) 89 fdntype ftype; 90 int ix; 91 struct mount *mp; 92 struct vnode **vpp; 93 { 94 struct fdcache *fc; 95 struct fdescnode *fd; 96 int error = 0; 97 98 loop: 99 fc = fdesc_hash(ix); 100 for (fd = fc->fc_forw; fd != (struct fdescnode *) fc; fd = fd->fd_forw) { 101 if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { 102 if (vget(fd->fd_vnode, 0)) 103 goto loop; 104 *vpp = fd->fd_vnode; 105 return (error); 106 } 107 } 108 109 /* 110 * otherwise lock the array while we call getnewvnode 111 * since that can block. 112 */ 113 if (fdcache_lock & FDL_LOCKED) { 114 fdcache_lock |= FDL_WANT; 115 sleep((caddr_t) &fdcache_lock, PINOD); 116 goto loop; 117 } 118 fdcache_lock |= FDL_LOCKED; 119 120 error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp); 121 if (error) 122 goto out; 123 MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); 124 (*vpp)->v_data = fd; 125 fd->fd_vnode = *vpp; 126 fd->fd_type = ftype; 127 fd->fd_fd = -1; 128 fd->fd_link = 0; 129 fd->fd_ix = ix; 130 fc = fdesc_hash(ix); 131 insque(fd, fc); 132 133 out:; 134 fdcache_lock &= ~FDL_LOCKED; 135 136 if (fdcache_lock & FDL_WANT) { 137 fdcache_lock &= ~FDL_WANT; 138 wakeup((caddr_t) &fdcache_lock); 139 } 140 141 return (error); 142 } 143 144 /* 145 * vp is the current namei directory 146 * ndp is the name to locate in that directory... 147 */ 148 int 149 fdesc_lookup(ap) 150 struct vop_lookup_args /* { 151 struct vnode * a_dvp; 152 struct vnode ** a_vpp; 153 struct componentname * a_cnp; 154 } */ *ap; 155 { 156 struct vnode **vpp = ap->a_vpp; 157 struct vnode *dvp = ap->a_dvp; 158 char *pname; 159 struct proc *p; 160 int nfiles; 161 unsigned fd; 162 int error; 163 struct vnode *fvp; 164 char *ln; 165 166 pname = ap->a_cnp->cn_nameptr; 167 if (ap->a_cnp->cn_namelen == 1 && *pname == '.') { 168 *vpp = dvp; 169 VREF(dvp); 170 VOP_LOCK(dvp); 171 return (0); 172 } 173 174 p = ap->a_cnp->cn_proc; 175 nfiles = p->p_fd->fd_nfiles; 176 177 switch (VTOFDESC(dvp)->fd_type) { 178 default: 179 case Flink: 180 case Fdesc: 181 case Fctty: 182 error = ENOTDIR; 183 goto bad; 184 185 case Froot: 186 if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) { 187 error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp); 188 if (error) 189 goto bad; 190 *vpp = fvp; 191 fvp->v_type = VDIR; 192 VOP_LOCK(fvp); 193 return (0); 194 } 195 196 if (ap->a_cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) { 197 struct vnode *ttyvp = cttyvp(p); 198 if (ttyvp == NULL) { 199 error = ENXIO; 200 goto bad; 201 } 202 error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp); 203 if (error) 204 goto bad; 205 *vpp = fvp; 206 fvp->v_type = VFIFO; 207 VOP_LOCK(fvp); 208 return (0); 209 } 210 211 ln = 0; 212 switch (ap->a_cnp->cn_namelen) { 213 case 5: 214 if (bcmp(pname, "stdin", 5) == 0) { 215 ln = "fd/0"; 216 fd = FD_STDIN; 217 } 218 break; 219 case 6: 220 if (bcmp(pname, "stdout", 6) == 0) { 221 ln = "fd/1"; 222 fd = FD_STDOUT; 223 } else 224 if (bcmp(pname, "stderr", 6) == 0) { 225 ln = "fd/2"; 226 fd = FD_STDERR; 227 } 228 break; 229 } 230 231 if (ln) { 232 error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp); 233 if (error) 234 goto bad; 235 VTOFDESC(fvp)->fd_link = ln; 236 *vpp = fvp; 237 fvp->v_type = VLNK; 238 VOP_LOCK(fvp); 239 return (0); 240 } else { 241 error = ENOENT; 242 goto bad; 243 } 244 245 /* FALL THROUGH */ 246 247 case Fdevfd: 248 if (ap->a_cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) { 249 error = fdesc_root(dvp->v_mount, vpp); 250 return (error); 251 } 252 253 fd = 0; 254 while (*pname >= '0' && *pname <= '9') { 255 fd = 10 * fd + *pname++ - '0'; 256 if (fd >= nfiles) 257 break; 258 } 259 260 if (*pname != '\0') { 261 error = ENOENT; 262 goto bad; 263 } 264 265 if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) { 266 error = EBADF; 267 goto bad; 268 } 269 270 error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); 271 if (error) 272 goto bad; 273 VTOFDESC(fvp)->fd_fd = fd; 274 *vpp = fvp; 275 return (0); 276 } 277 278 bad:; 279 *vpp = NULL; 280 return (error); 281 } 282 283 int 284 fdesc_open(ap) 285 struct vop_open_args /* { 286 struct vnode *a_vp; 287 int a_mode; 288 struct ucred *a_cred; 289 struct proc *a_p; 290 } */ *ap; 291 { 292 struct vnode *vp = ap->a_vp; 293 int error = 0; 294 295 switch (VTOFDESC(vp)->fd_type) { 296 case Fdesc: 297 /* 298 * XXX Kludge: set p->p_dupfd to contain the value of the 299 * the file descriptor being sought for duplication. The error 300 * return ensures that the vnode for this device will be 301 * released by vn_open. Open will detect this special error and 302 * take the actions in dupfdopen. Other callers of vn_open or 303 * VOP_OPEN will simply report the error. 304 */ 305 ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ 306 error = ENODEV; 307 break; 308 309 case Fctty: 310 error = cttyopen(devctty, ap->a_mode, 0, ap->a_p); 311 break; 312 } 313 314 return (error); 315 } 316 317 static int 318 fdesc_attr(fd, vap, cred, p) 319 int fd; 320 struct vattr *vap; 321 struct ucred *cred; 322 struct proc *p; 323 { 324 struct filedesc *fdp = p->p_fd; 325 struct file *fp; 326 struct stat stb; 327 int error; 328 329 if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) 330 return (EBADF); 331 332 switch (fp->f_type) { 333 case DTYPE_VNODE: 334 error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p); 335 if (error == 0 && vap->va_type == VDIR) { 336 /* 337 * don't allow directories to show up because 338 * that causes loops in the namespace. 339 */ 340 vap->va_type = VFIFO; 341 } 342 break; 343 344 case DTYPE_SOCKET: 345 error = soo_stat((struct socket *)fp->f_data, &stb); 346 if (error == 0) { 347 vattr_null(vap); 348 vap->va_type = VSOCK; 349 vap->va_mode = stb.st_mode; 350 vap->va_nlink = stb.st_nlink; 351 vap->va_uid = stb.st_uid; 352 vap->va_gid = stb.st_gid; 353 vap->va_fsid = stb.st_dev; 354 vap->va_fileid = stb.st_ino; 355 vap->va_size = stb.st_size; 356 vap->va_blocksize = stb.st_blksize; 357 vap->va_atime = stb.st_atimespec; 358 vap->va_mtime = stb.st_mtimespec; 359 vap->va_ctime = stb.st_ctimespec; 360 vap->va_gen = stb.st_gen; 361 vap->va_flags = stb.st_flags; 362 vap->va_rdev = stb.st_rdev; 363 vap->va_bytes = stb.st_blocks * stb.st_blksize; 364 } 365 break; 366 367 default: 368 panic("fdesc attr"); 369 break; 370 } 371 372 return (error); 373 } 374 375 int 376 fdesc_getattr(ap) 377 struct vop_getattr_args /* { 378 struct vnode *a_vp; 379 struct vattr *a_vap; 380 struct ucred *a_cred; 381 struct proc *a_p; 382 } */ *ap; 383 { 384 struct vnode *vp = ap->a_vp; 385 struct vattr *vap = ap->a_vap; 386 unsigned fd; 387 int error = 0; 388 389 switch (VTOFDESC(vp)->fd_type) { 390 case Froot: 391 case Fdevfd: 392 case Flink: 393 case Fctty: 394 bzero((caddr_t) vap, sizeof(*vap)); 395 vattr_null(vap); 396 vap->va_fileid = VTOFDESC(vp)->fd_ix; 397 398 switch (VTOFDESC(vp)->fd_type) { 399 case Flink: 400 vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 401 vap->va_type = VLNK; 402 vap->va_nlink = 1; 403 vap->va_size = strlen(VTOFDESC(vp)->fd_link); 404 break; 405 406 case Fctty: 407 vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; 408 vap->va_type = VFIFO; 409 vap->va_nlink = 1; 410 vap->va_size = 0; 411 break; 412 413 default: 414 vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 415 vap->va_type = VDIR; 416 vap->va_nlink = 2; 417 vap->va_size = DEV_BSIZE; 418 break; 419 } 420 vap->va_uid = 0; 421 vap->va_gid = 0; 422 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 423 vap->va_blocksize = DEV_BSIZE; 424 vap->va_atime.ts_sec = boottime.tv_sec; 425 vap->va_atime.ts_nsec = 0; 426 vap->va_mtime = vap->va_atime; 427 vap->va_ctime = vap->va_mtime; 428 vap->va_gen = 0; 429 vap->va_flags = 0; 430 vap->va_rdev = 0; 431 vap->va_bytes = 0; 432 break; 433 434 case Fdesc: 435 fd = VTOFDESC(vp)->fd_fd; 436 error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p); 437 break; 438 439 default: 440 panic("fdesc_getattr"); 441 break; 442 } 443 444 if (error == 0) 445 vp->v_type = vap->va_type; 446 447 return (error); 448 } 449 450 int 451 fdesc_setattr(ap) 452 struct vop_setattr_args /* { 453 struct vnode *a_vp; 454 struct vattr *a_vap; 455 struct ucred *a_cred; 456 struct proc *a_p; 457 } */ *ap; 458 { 459 struct filedesc *fdp = ap->a_p->p_fd; 460 struct file *fp; 461 unsigned fd; 462 int error; 463 464 /* 465 * Can't mess with the root vnode 466 */ 467 switch (VTOFDESC(ap->a_vp)->fd_type) { 468 case Fdesc: 469 break; 470 471 case Fctty: 472 return (0); 473 474 default: 475 return (EACCES); 476 } 477 478 fd = VTOFDESC(ap->a_vp)->fd_fd; 479 if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { 480 return (EBADF); 481 } 482 483 /* 484 * Can setattr the underlying vnode, but not sockets! 485 */ 486 switch (fp->f_type) { 487 case DTYPE_VNODE: 488 error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p); 489 break; 490 491 case DTYPE_SOCKET: 492 error = 0; 493 break; 494 495 default: 496 panic("fdesc setattr"); 497 break; 498 } 499 500 return (error); 501 } 502 503 #define UIO_MX 16 504 505 static struct dirtmp { 506 u_long d_fileno; 507 u_short d_reclen; 508 u_short d_namlen; 509 char d_name[8]; 510 } rootent[] = { 511 { FD_DEVFD, UIO_MX, 2, "fd" }, 512 { FD_STDIN, UIO_MX, 5, "stdin" }, 513 { FD_STDOUT, UIO_MX, 6, "stdout" }, 514 { FD_STDERR, UIO_MX, 6, "stderr" }, 515 { FD_CTTY, UIO_MX, 3, "tty" }, 516 { 0 } 517 }; 518 519 int 520 fdesc_readdir(ap) 521 struct vop_readdir_args /* { 522 struct vnode *a_vp; 523 struct uio *a_uio; 524 struct ucred *a_cred; 525 } */ *ap; 526 { 527 struct uio *uio = ap->a_uio; 528 struct filedesc *fdp; 529 int i; 530 int error; 531 532 switch (VTOFDESC(ap->a_vp)->fd_type) { 533 case Fctty: 534 return (0); 535 536 case Fdesc: 537 return (ENOTDIR); 538 539 default: 540 break; 541 } 542 543 fdp = uio->uio_procp->p_fd; 544 545 if (VTOFDESC(ap->a_vp)->fd_type == Froot) { 546 struct dirent d; 547 struct dirent *dp = &d; 548 struct dirtmp *dt; 549 550 i = uio->uio_offset / UIO_MX; 551 error = 0; 552 553 while (uio->uio_resid > 0) { 554 dt = &rootent[i]; 555 if (dt->d_fileno == 0) { 556 /**eofflagp = 1;*/ 557 break; 558 } 559 i++; 560 561 switch (dt->d_fileno) { 562 case FD_CTTY: 563 if (cttyvp(uio->uio_procp) == NULL) 564 continue; 565 break; 566 567 case FD_STDIN: 568 case FD_STDOUT: 569 case FD_STDERR: 570 if ((dt->d_fileno-FD_STDIN) >= fdp->fd_nfiles) 571 continue; 572 if (fdp->fd_ofiles[dt->d_fileno-FD_STDIN] == NULL) 573 continue; 574 break; 575 } 576 bzero((caddr_t) dp, UIO_MX); 577 dp->d_fileno = dt->d_fileno; 578 dp->d_namlen = dt->d_namlen; 579 dp->d_type = DT_UNKNOWN; 580 dp->d_reclen = dt->d_reclen; 581 bcopy(dt->d_name, dp->d_name, dp->d_namlen+1); 582 error = uiomove((caddr_t) dp, UIO_MX, uio); 583 if (error) 584 break; 585 } 586 uio->uio_offset = i * UIO_MX; 587 return (error); 588 } 589 590 i = uio->uio_offset / UIO_MX; 591 error = 0; 592 while (uio->uio_resid > 0) { 593 if (i >= fdp->fd_nfiles) 594 break; 595 596 if (fdp->fd_ofiles[i] != NULL) { 597 struct dirent d; 598 struct dirent *dp = &d; 599 600 bzero((caddr_t) dp, UIO_MX); 601 602 dp->d_namlen = sprintf(dp->d_name, "%d", i); 603 dp->d_reclen = UIO_MX; 604 dp->d_type = DT_UNKNOWN; 605 dp->d_fileno = i + FD_STDIN; 606 /* 607 * And ship to userland 608 */ 609 error = uiomove((caddr_t) dp, UIO_MX, uio); 610 if (error) 611 break; 612 } 613 i++; 614 } 615 616 uio->uio_offset = i * UIO_MX; 617 return (error); 618 } 619 620 int 621 fdesc_readlink(ap) 622 struct vop_readlink_args /* { 623 struct vnode *a_vp; 624 struct uio *a_uio; 625 struct ucred *a_cred; 626 } */ *ap; 627 { 628 struct vnode *vp = ap->a_vp; 629 int error; 630 631 if (vp->v_type != VLNK) 632 return (EPERM); 633 634 if (VTOFDESC(vp)->fd_type == Flink) { 635 char *ln = VTOFDESC(vp)->fd_link; 636 error = uiomove(ln, strlen(ln), ap->a_uio); 637 } else { 638 error = EOPNOTSUPP; 639 } 640 641 return (error); 642 } 643 644 int 645 fdesc_read(ap) 646 struct vop_read_args /* { 647 struct vnode *a_vp; 648 struct uio *a_uio; 649 int a_ioflag; 650 struct ucred *a_cred; 651 } */ *ap; 652 { 653 int error = EOPNOTSUPP; 654 655 switch (VTOFDESC(ap->a_vp)->fd_type) { 656 case Fctty: 657 error = cttyread(devctty, ap->a_uio, ap->a_ioflag); 658 break; 659 660 default: 661 error = EOPNOTSUPP; 662 break; 663 } 664 665 return (error); 666 } 667 668 int 669 fdesc_write(ap) 670 struct vop_write_args /* { 671 struct vnode *a_vp; 672 struct uio *a_uio; 673 int a_ioflag; 674 struct ucred *a_cred; 675 } */ *ap; 676 { 677 int error = EOPNOTSUPP; 678 679 switch (VTOFDESC(ap->a_vp)->fd_type) { 680 case Fctty: 681 error = cttywrite(devctty, ap->a_uio, ap->a_ioflag); 682 break; 683 684 default: 685 error = EOPNOTSUPP; 686 break; 687 } 688 689 return (error); 690 } 691 692 int 693 fdesc_ioctl(ap) 694 struct vop_ioctl_args /* { 695 struct vnode *a_vp; 696 int a_command; 697 caddr_t a_data; 698 int a_fflag; 699 struct ucred *a_cred; 700 struct proc *a_p; 701 } */ *ap; 702 { 703 int error = EOPNOTSUPP; 704 705 switch (VTOFDESC(ap->a_vp)->fd_type) { 706 case Fctty: 707 error = cttyioctl(devctty, ap->a_command, ap->a_data, 708 ap->a_fflag, ap->a_p); 709 break; 710 711 default: 712 error = EOPNOTSUPP; 713 break; 714 } 715 716 return (error); 717 } 718 719 int 720 fdesc_select(ap) 721 struct vop_select_args /* { 722 struct vnode *a_vp; 723 int a_which; 724 int a_fflags; 725 struct ucred *a_cred; 726 struct proc *a_p; 727 } */ *ap; 728 { 729 int error = EOPNOTSUPP; 730 731 switch (VTOFDESC(ap->a_vp)->fd_type) { 732 case Fctty: 733 error = cttyselect(devctty, ap->a_fflags, ap->a_p); 734 break; 735 736 default: 737 error = EOPNOTSUPP; 738 break; 739 } 740 741 return (error); 742 } 743 744 int 745 fdesc_inactive(ap) 746 struct vop_inactive_args /* { 747 struct vnode *a_vp; 748 } */ *ap; 749 { 750 struct vnode *vp = ap->a_vp; 751 752 /* 753 * Clear out the v_type field to avoid 754 * nasty things happening in vgone(). 755 */ 756 vp->v_type = VNON; 757 return (0); 758 } 759 760 int 761 fdesc_reclaim(ap) 762 struct vop_reclaim_args /* { 763 struct vnode *a_vp; 764 } */ *ap; 765 { 766 struct vnode *vp = ap->a_vp; 767 768 remque(VTOFDESC(vp)); 769 FREE(vp->v_data, M_TEMP); 770 vp->v_data = 0; 771 772 return (0); 773 } 774 775 /* 776 * Print out the contents of a /dev/fd vnode. 777 */ 778 /* ARGSUSED */ 779 int 780 fdesc_print(ap) 781 struct vop_print_args /* { 782 struct vnode *a_vp; 783 } */ *ap; 784 { 785 786 printf("tag VT_NON, fdesc vnode\n"); 787 return (0); 788 } 789 790 /*void*/ 791 int 792 fdesc_vfree(ap) 793 struct vop_vfree_args /* { 794 struct vnode *a_pvp; 795 ino_t a_ino; 796 int a_mode; 797 } */ *ap; 798 { 799 800 return (0); 801 } 802 803 /* 804 * /dev/fd vnode unsupported operation 805 */ 806 int 807 fdesc_enotsupp() 808 { 809 810 return (EOPNOTSUPP); 811 } 812 813 /* 814 * /dev/fd "should never get here" operation 815 */ 816 int 817 fdesc_badop() 818 { 819 820 panic("fdesc: bad op"); 821 /* NOTREACHED */ 822 } 823 824 /* 825 * /dev/fd vnode null operation 826 */ 827 int 828 fdesc_nullop() 829 { 830 831 return (0); 832 } 833 834 #define fdesc_create ((int (*) __P((struct vop_create_args *)))fdesc_enotsupp) 835 #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))fdesc_enotsupp) 836 #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop) 837 #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop) 838 #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))fdesc_enotsupp) 839 #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) 840 #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop) 841 #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))fdesc_enotsupp) 842 #define fdesc_link ((int (*) __P((struct vop_link_args *)))fdesc_enotsupp) 843 #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))fdesc_enotsupp) 844 #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))fdesc_enotsupp) 845 #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))fdesc_enotsupp) 846 #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))fdesc_enotsupp) 847 #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) 848 #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))nullop) 849 #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))nullop) 850 #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop) 851 #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop) 852 #define fdesc_islocked ((int (*) __P((struct vop_islocked_args *)))nullop) 853 #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))fdesc_enotsupp) 854 #define fdesc_blkatoff \ 855 ((int (*) __P((struct vop_blkatoff_args *)))fdesc_enotsupp) 856 #define fdesc_vget ((int (*) __P((struct vop_vget_args *)))fdesc_enotsupp) 857 #define fdesc_valloc ((int(*) __P(( \ 858 struct vnode *pvp, \ 859 int mode, \ 860 struct ucred *cred, \ 861 struct vnode **vpp))) fdesc_enotsupp) 862 #define fdesc_truncate \ 863 ((int (*) __P((struct vop_truncate_args *)))fdesc_enotsupp) 864 #define fdesc_update ((int (*) __P((struct vop_update_args *)))fdesc_enotsupp) 865 #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))fdesc_enotsupp) 866 867 int (**fdesc_vnodeop_p)(); 868 struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = { 869 { &vop_default_desc, vn_default_error }, 870 { &vop_lookup_desc, fdesc_lookup }, /* lookup */ 871 { &vop_create_desc, fdesc_create }, /* create */ 872 { &vop_mknod_desc, fdesc_mknod }, /* mknod */ 873 { &vop_open_desc, fdesc_open }, /* open */ 874 { &vop_close_desc, fdesc_close }, /* close */ 875 { &vop_access_desc, fdesc_access }, /* access */ 876 { &vop_getattr_desc, fdesc_getattr }, /* getattr */ 877 { &vop_setattr_desc, fdesc_setattr }, /* setattr */ 878 { &vop_read_desc, fdesc_read }, /* read */ 879 { &vop_write_desc, fdesc_write }, /* write */ 880 { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */ 881 { &vop_select_desc, fdesc_select }, /* select */ 882 { &vop_mmap_desc, fdesc_mmap }, /* mmap */ 883 { &vop_fsync_desc, fdesc_fsync }, /* fsync */ 884 { &vop_seek_desc, fdesc_seek }, /* seek */ 885 { &vop_remove_desc, fdesc_remove }, /* remove */ 886 { &vop_link_desc, fdesc_link }, /* link */ 887 { &vop_rename_desc, fdesc_rename }, /* rename */ 888 { &vop_mkdir_desc, fdesc_mkdir }, /* mkdir */ 889 { &vop_rmdir_desc, fdesc_rmdir }, /* rmdir */ 890 { &vop_symlink_desc, fdesc_symlink }, /* symlink */ 891 { &vop_readdir_desc, fdesc_readdir }, /* readdir */ 892 { &vop_readlink_desc, fdesc_readlink }, /* readlink */ 893 { &vop_abortop_desc, fdesc_abortop }, /* abortop */ 894 { &vop_inactive_desc, fdesc_inactive }, /* inactive */ 895 { &vop_reclaim_desc, fdesc_reclaim }, /* reclaim */ 896 { &vop_lock_desc, fdesc_lock }, /* lock */ 897 { &vop_unlock_desc, fdesc_unlock }, /* unlock */ 898 { &vop_bmap_desc, fdesc_bmap }, /* bmap */ 899 { &vop_strategy_desc, fdesc_strategy }, /* strategy */ 900 { &vop_print_desc, fdesc_print }, /* print */ 901 { &vop_islocked_desc, fdesc_islocked }, /* islocked */ 902 { &vop_advlock_desc, fdesc_advlock }, /* advlock */ 903 { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */ 904 { &vop_valloc_desc, fdesc_valloc }, /* valloc */ 905 { &vop_vfree_desc, fdesc_vfree }, /* vfree */ 906 { &vop_truncate_desc, fdesc_truncate }, /* truncate */ 907 { &vop_update_desc, fdesc_update }, /* update */ 908 { &vop_bwrite_desc, fdesc_bwrite }, /* bwrite */ 909 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 910 }; 911 struct vnodeopv_desc fdesc_vnodeop_opv_desc = 912 { &fdesc_vnodeop_p, fdesc_vnodeop_entries }; 913