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