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