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