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