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