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