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 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * From: 38 * Id: fdesc_vnops.c,v 4.1 1993/12/17 10:47:45 jsp Rel 39 * 40 * $Id: fdesc_vnops.c,v 1.13 1994/05/04 03:42:14 cgd Exp $ 41 */ 42 43 /* 44 * /dev/fd Filesystem 45 */ 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/types.h> 50 #include <sys/time.h> 51 #include <sys/proc.h> 52 #include <sys/kernel.h> /* boottime */ 53 #include <sys/resourcevar.h> 54 #include <sys/filedesc.h> 55 #include <sys/vnode.h> 56 #include <sys/file.h> 57 #include <sys/stat.h> 58 #include <sys/mount.h> 59 #include <sys/namei.h> 60 #include <sys/buf.h> 61 #include <miscfs/fdesc/fdesc.h> 62 63 #include <ufs/dir.h> /* For readdir() XXX */ 64 65 #define cttyvp(p) ((p)->p_flag&P_CONTROLT ? (p)->p_session->s_ttyvp : NULL) 66 67 #define FDL_WANT 0x01 68 #define FDL_LOCKED 0x02 69 static int fdescvplock; 70 static struct vnode *fdescvp[FD_MAX]; 71 72 #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1) 73 FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2 74 #endif 75 76 fdesc_allocvp(ftype, ix, mp, vpp) 77 fdntype ftype; 78 int ix; 79 struct mount *mp; 80 struct vnode **vpp; 81 { 82 struct vnode **nvpp = 0; 83 int error = 0; 84 85 loop: 86 /* get stashed copy of the vnode */ 87 if (ix >= 0 && ix < FD_MAX && ix != FD_ROOT) { 88 nvpp = &fdescvp[ix]; 89 if (*nvpp) { 90 if (vget(*nvpp, 1)) 91 goto loop; 92 VOP_UNLOCK(*nvpp); 93 *vpp = *nvpp; 94 return (error); 95 } 96 } 97 98 /* 99 * otherwise lock the array while we call getnewvnode 100 * since that can block. 101 */ 102 if (fdescvplock & FDL_LOCKED) { 103 fdescvplock |= FDL_WANT; 104 sleep((caddr_t) &fdescvplock, PINOD); 105 goto loop; 106 } 107 fdescvplock |= FDL_LOCKED; 108 109 error = getnewvnode(VT_FDESC, mp, &fdesc_vnodeops, vpp); 110 if (error) 111 goto out; 112 if (nvpp) 113 *nvpp = *vpp; 114 VTOFDESC(*vpp)->fd_type = ftype; 115 VTOFDESC(*vpp)->fd_fd = -1; 116 VTOFDESC(*vpp)->fd_link = 0; 117 VTOFDESC(*vpp)->fd_ix = ix; 118 119 out:; 120 fdescvplock &= ~FDL_LOCKED; 121 122 if (fdescvplock & FDL_WANT) { 123 fdescvplock &= ~FDL_WANT; 124 wakeup((caddr_t) &fdescvplock); 125 } 126 127 return (error); 128 } 129 130 /* 131 * vp is the current namei directory 132 * ndp is the name to locate in that directory... 133 */ 134 fdesc_lookup(dvp, ndp, p) 135 struct vnode *dvp; 136 struct nameidata *ndp; 137 struct proc *p; 138 { 139 char *pname = ndp->ni_ptr; 140 int nfiles = p->p_fd->fd_nfiles; 141 unsigned fd; 142 int error; 143 struct vnode *fvp; 144 char *ln; 145 146 #ifdef FDESC_DIAGNOSTIC 147 printf("fdesc_lookup(%s)\n", pname); 148 #endif 149 if (ndp->ni_namelen == 1 && *pname == '.') { 150 ndp->ni_dvp = dvp; 151 ndp->ni_vp = dvp; 152 VREF(dvp); 153 VOP_LOCK(dvp); 154 return (0); 155 } 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 (ndp->ni_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 ndp->ni_dvp = dvp; 171 ndp->ni_vp = fvp; 172 fvp->v_type = VDIR; 173 VOP_LOCK(fvp); 174 #ifdef FDESC_DIAGNOSTIC 175 printf("fdesc_lookup: newvp = %x\n", fvp); 176 #endif 177 return (0); 178 } 179 180 if (ndp->ni_namelen == 3 && bcmp(pname, "tty", 3) == 0) { 181 struct vnode *ttyvp = cttyvp(p); 182 if (ttyvp == NULL) { 183 error = ENXIO; 184 goto bad; 185 } 186 error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp); 187 if (error) 188 goto bad; 189 ndp->ni_dvp = dvp; 190 ndp->ni_vp = fvp; 191 fvp->v_type = VFIFO; 192 VOP_LOCK(fvp); 193 #ifdef FDESC_DIAGNOSTIC 194 printf("fdesc_lookup: ttyvp = %x\n", fvp); 195 #endif 196 return (0); 197 } 198 199 ln = 0; 200 switch (ndp->ni_namelen) { 201 case 5: 202 if (bcmp(pname, "stdin", 5) == 0) { 203 ln = "fd/0"; 204 fd = FD_STDIN; 205 } 206 break; 207 case 6: 208 if (bcmp(pname, "stdout", 6) == 0) { 209 ln = "fd/1"; 210 fd = FD_STDOUT; 211 } else 212 if (bcmp(pname, "stderr", 6) == 0) { 213 ln = "fd/2"; 214 fd = FD_STDERR; 215 } 216 break; 217 } 218 219 if (ln) { 220 #ifdef FDESC_DIAGNOSTIC 221 printf("fdesc_lookup: link -> %s\n", ln); 222 #endif 223 error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp); 224 if (error) 225 goto bad; 226 VTOFDESC(fvp)->fd_link = ln; 227 ndp->ni_dvp = dvp; 228 ndp->ni_vp = fvp; 229 fvp->v_type = VLNK; 230 VOP_LOCK(fvp); 231 #ifdef FDESC_DIAGNOSTIC 232 printf("fdesc_lookup: newvp = %x\n", fvp); 233 #endif 234 return (0); 235 } else { 236 error = ENOENT; 237 goto bad; 238 } 239 240 /* fall through */ 241 242 case Fdevfd: 243 if (ndp->ni_namelen == 2 && bcmp(pname, "..", 2) == 0) { 244 ndp->ni_dvp = dvp; 245 error = fdesc_root(dvp->v_mount, &ndp->ni_vp); 246 return (error); 247 } 248 249 fd = 0; 250 while (*pname >= '0' && *pname <= '9') { 251 fd = 10 * fd + *pname++ - '0'; 252 if (fd >= nfiles) 253 break; 254 } 255 256 #ifdef FDESC_DIAGNOSTIC 257 printf("fdesc_lookup: fd = %d, *pname = %x\n", fd, *pname); 258 #endif 259 if (*pname == '/') { 260 error = ENOTDIR; 261 goto bad; 262 } 263 264 if (*pname != '\0') { 265 error = ENOENT; 266 goto bad; 267 } 268 269 devfd: 270 if (fd >= nfiles || p->p_fd->fd_ofiles[fd] == NULL) { 271 error = EBADF; 272 goto bad; 273 } 274 275 #ifdef FDESC_DIAGNOSTIC 276 printf("fdesc_lookup: allocate new vnode\n"); 277 #endif 278 error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); 279 if (error) 280 goto bad; 281 VTOFDESC(fvp)->fd_fd = fd; 282 ndp->ni_dvp = dvp; 283 ndp->ni_vp = fvp; 284 #ifdef FDESC_DIAGNOSTIC 285 printf("fdesc_lookup: newvp = %x\n", fvp); 286 #endif 287 return (0); 288 } 289 290 bad:; 291 ndp->ni_dvp = dvp; 292 ndp->ni_vp = NULL; 293 #ifdef FDESC_DIAGNOSTIC 294 printf("fdesc_lookup: error = %d\n", error); 295 #endif 296 return (error); 297 } 298 299 fdesc_open(vp, mode, cred, p) 300 struct vnode *vp; 301 int mode; 302 struct ucred *cred; 303 struct proc *p; 304 { 305 int error = 0; 306 307 switch (VTOFDESC(vp)->fd_type) { 308 case Fdesc: 309 /* 310 * XXX Kludge: set p->p_dupfd to contain the value of the 311 * the file descriptor being sought for duplication. The error 312 * return ensures that the vnode for this device will be 313 * released by vn_open. Open will detect this special error and 314 * take the actions in dupfdopen. Other callers of vn_open or 315 * VOP_OPEN will simply report the error. 316 */ 317 p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ 318 error = ENODEV; 319 break; 320 321 case Fctty: 322 error = cttyopen(devctty, mode, 0, p); 323 break; 324 } 325 326 return (error); 327 } 328 329 static int 330 fdesc_attr(fd, vap, cred, p) 331 int fd; 332 struct vattr *vap; 333 struct ucred *cred; 334 struct proc *p; 335 { 336 struct filedesc *fdp = p->p_fd; 337 struct file *fp; 338 struct stat stb; 339 int error; 340 341 #ifdef FDESC_DIAGNOSTIC 342 printf("fdesc_attr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles); 343 #endif 344 if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { 345 #ifdef FDESC_DIAGNOSTIC 346 printf("fdesc_attr: fp = %x (EBADF)\n", fp); 347 #endif 348 return (EBADF); 349 } 350 351 /* 352 * Can stat the underlying vnode, but not sockets because 353 * they don't use struct vattrs. Well, we could convert from 354 * a struct stat back to a struct vattr, later... 355 */ 356 switch (fp->f_type) { 357 case DTYPE_VNODE: 358 error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p); 359 if (error == 0 && vap->va_type == VDIR) { 360 /* 361 * don't allow directories to show up because 362 * that causes loops in the namespace. 363 */ 364 vap->va_type = VFIFO; 365 } 366 break; 367 368 case DTYPE_SOCKET: 369 error = soo_stat((struct socket *)fp->f_data, &stb); 370 if (error == 0) { 371 vattr_null(vap); 372 vap->va_type = VSOCK; 373 vap->va_mode = stb.st_mode; 374 vap->va_nlink = stb.st_nlink; 375 vap->va_uid = stb.st_uid; 376 vap->va_gid = stb.st_gid; 377 vap->va_fsid = stb.st_dev; 378 vap->va_fileid = stb.st_ino; 379 vap->va_size = stb.st_size; 380 vap->va_blocksize = stb.st_blksize; 381 vap->va_atime = stb.st_atimespec; 382 vap->va_mtime = stb.st_mtimespec; 383 vap->va_ctime = stb.st_ctimespec; 384 vap->va_gen = stb.st_gen; 385 vap->va_flags = stb.st_flags; 386 vap->va_rdev = stb.st_rdev; 387 vap->va_bytes = stb.st_blocks * stb.st_blksize; 388 } 389 break; 390 391 default: 392 panic("fdesc attr"); 393 break; 394 } 395 396 #ifdef FDESC_DIAGNOSTIC 397 printf("fdesc_attr: returns error %d\n", error); 398 #endif 399 return (error); 400 } 401 402 fdesc_getattr(vp, vap, cred, p) 403 struct vnode *vp; 404 struct vattr *vap; 405 struct ucred *cred; 406 struct proc *p; 407 { 408 unsigned fd; 409 int error = 0; 410 411 #ifdef FDESC_DIAGNOSTIC 412 printf("fdesc_getattr: stat type = %d\n", VTOFDESC(vp)->fd_type); 413 #endif 414 415 switch (VTOFDESC(vp)->fd_type) { 416 case Froot: 417 case Fdevfd: 418 case Flink: 419 case Fctty: 420 bzero((caddr_t) vap, sizeof(*vap)); 421 vattr_null(vap); 422 vap->va_fileid = VTOFDESC(vp)->fd_ix; 423 424 switch (VTOFDESC(vp)->fd_type) { 425 case Flink: 426 vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 427 vap->va_type = VLNK; 428 vap->va_nlink = 1; 429 /* vap->va_qsize = strlen(VTOFDESC(vp)->fd_link); */ 430 vap->va_size = strlen(VTOFDESC(vp)->fd_link); 431 break; 432 433 case Fctty: 434 vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; 435 vap->va_type = VFIFO; 436 vap->va_nlink = 1; 437 /* vap->va_qsize = 0; */ 438 vap->va_size = 0; 439 break; 440 441 default: 442 vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; 443 vap->va_type = VDIR; 444 vap->va_nlink = 2; 445 /* vap->va_qsize = 0; */ 446 vap->va_size = DEV_BSIZE; 447 break; 448 } 449 vap->va_uid = 0; 450 vap->va_gid = 0; 451 vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; 452 vap->va_blocksize = DEV_BSIZE; 453 TIMEVAL_TO_TIMESPEC(&boottime, &vap->va_atime); 454 vap->va_mtime = vap->va_atime; 455 vap->va_ctime = vap->va_ctime; 456 vap->va_gen = 0; 457 vap->va_flags = 0; 458 vap->va_rdev = 0; 459 /* vap->va_qbytes = 0; */ 460 vap->va_bytes = 0; 461 break; 462 463 case Fdesc: 464 #ifdef FDESC_DIAGNOSTIC 465 printf("fdesc_getattr: stat desc #%d\n", VTOFDESC(vp)->fd_fd); 466 #endif 467 fd = VTOFDESC(vp)->fd_fd; 468 error = fdesc_attr(fd, vap, cred, p); 469 break; 470 471 default: 472 panic("fdesc_getattr"); 473 break; 474 } 475 476 if (error == 0) 477 vp->v_type = vap->va_type; 478 479 #ifdef FDESC_DIAGNOSTIC 480 printf("fdesc_getattr: stat returns 0\n"); 481 #endif 482 return (error); 483 } 484 485 fdesc_setattr(vp, vap, cred, p) 486 struct vnode *vp; 487 struct vattr *vap; 488 struct ucred *cred; 489 struct proc *p; 490 { 491 struct filedesc *fdp = p->p_fd; 492 struct file *fp; 493 unsigned fd; 494 int error; 495 496 /* 497 * Can't mess with the root vnode 498 */ 499 switch (VTOFDESC(vp)->fd_type) { 500 case Fdesc: 501 break; 502 503 case Fctty: 504 return (0); 505 506 default: 507 return (EACCES); 508 } 509 510 fd = VTOFDESC(vp)->fd_fd; 511 #ifdef FDESC_DIAGNOSTIC 512 printf("fdesc_setattr: fd = %d, nfiles = %d\n", fd, fdp->fd_nfiles); 513 #endif 514 if (fd >= fdp->fd_nfiles || (fp = fdp->fd_ofiles[fd]) == NULL) { 515 #ifdef FDESC_DIAGNOSTIC 516 printf("fdesc_setattr: fp = %x (EBADF)\n", fp); 517 #endif 518 return (EBADF); 519 } 520 521 /* 522 * Can setattr the underlying vnode, but not sockets! 523 */ 524 switch (fp->f_type) { 525 case DTYPE_VNODE: 526 error = VOP_SETATTR((struct vnode *) fp->f_data, vap, cred, p); 527 break; 528 529 case DTYPE_SOCKET: 530 error = 0; /* EOPNOTSUPP? */ 531 break; 532 533 default: 534 panic("fdesc setattr"); 535 break; 536 } 537 538 #ifdef FDESC_DIAGNOSTIC 539 printf("fdesc_setattr: returns error %d\n", error); 540 #endif 541 return (error); 542 } 543 544 #define UIO_MX 16 545 546 static struct dirtmp { 547 u_long d_ino; 548 u_short d_reclen; 549 u_short d_namlen; 550 char d_name[8]; 551 } rootent[] = { 552 { FD_DEVFD, UIO_MX, 2, "fd" }, 553 { FD_STDIN, UIO_MX, 5, "stdin" }, 554 { FD_STDOUT, UIO_MX, 6, "stdout" }, 555 { FD_STDERR, UIO_MX, 6, "stderr" }, 556 { FD_CTTY, UIO_MX, 3, "tty" }, 557 { 0 } 558 }; 559 560 fdesc_readdir(vp, uio, cred, eofflagp, cookies, ncookies) 561 struct vnode *vp; 562 struct uio *uio; 563 struct ucred *cred; 564 int *eofflagp; 565 u_int *cookies; 566 int ncookies; 567 { 568 struct filedesc *fdp; 569 int i; 570 int error; 571 572 /* 573 * NFS mounting of fdesc doesn't make sense 574 * See also fdesc_vptofh & fdesc_fhtovp in fdesc_vfsops.c 575 */ 576 if (cookies) 577 panic("fdesc_readdir"); 578 579 switch (VTOFDESC(vp)->fd_type) { 580 case Fctty: 581 return (0); 582 583 case Fdesc: 584 return (ENOTDIR); 585 586 default: 587 break; 588 } 589 590 fdp = uio->uio_procp->p_fd; 591 592 if (VTOFDESC(vp)->fd_type == Froot) { 593 struct direct d; 594 struct direct *dp = &d; 595 struct dirtmp *dt; 596 597 i = uio->uio_offset / UIO_MX; 598 error = 0; 599 600 while (uio->uio_resid > 0) { 601 dt = &rootent[i]; 602 if (dt->d_ino == 0) { 603 *eofflagp = 1; 604 break; 605 } 606 i++; 607 608 switch (dt->d_ino) { 609 case FD_CTTY: 610 if (cttyvp(uio->uio_procp) == NULL) 611 continue; 612 break; 613 614 case FD_STDIN: 615 case FD_STDOUT: 616 case FD_STDERR: 617 if ((dt->d_ino-FD_STDIN) >= fdp->fd_nfiles) 618 continue; 619 if (fdp->fd_ofiles[dt->d_ino-FD_STDIN] == NULL) 620 continue; 621 break; 622 } 623 bzero(dp, UIO_MX); 624 dp->d_ino = dt->d_ino; 625 dp->d_namlen = dt->d_namlen; 626 dp->d_reclen = dt->d_reclen; 627 bcopy(dt->d_name, dp->d_name, dp->d_namlen+1); 628 error = uiomove((caddr_t) dp, UIO_MX, uio); 629 if (error) 630 break; 631 } 632 uio->uio_offset = i * UIO_MX; 633 return (error); 634 } 635 636 i = uio->uio_offset / UIO_MX; 637 error = 0; 638 while (uio->uio_resid > 0) { 639 if (i >= fdp->fd_nfiles) { 640 *eofflagp = 1; 641 break; 642 } 643 if (fdp->fd_ofiles[i] != NULL) { 644 struct direct d; 645 struct direct *dp = &d; 646 #ifdef FDESC_FILEID 647 struct vattr va; 648 #endif 649 bzero((caddr_t) dp, UIO_MX); 650 651 dp->d_namlen = sprintf(dp->d_name, "%d", i); 652 /* 653 * Fill in the remaining fields 654 */ 655 dp->d_reclen = UIO_MX; 656 dp->d_ino = i + FD_STDIN; 657 #ifdef FDESC_FILEID 658 /* 659 * If we want the file ids to match the 660 * we must call getattr on the underlying file. 661 * fdesc_attr may return an error, in which case 662 * we ignore the returned file id. 663 */ 664 error = fdesc_attr(i, &va, cred, p); 665 if (error == 0) 666 dp->d_ino = va.va_fileid; 667 #endif 668 /* 669 * And ship to userland 670 */ 671 error = uiomove((caddr_t) dp, UIO_MX, uio); 672 if (error) 673 break; 674 } 675 i++; 676 } 677 678 uio->uio_offset = i * UIO_MX; 679 return (error); 680 } 681 682 fdesc_readlink(vp, uio, cred) 683 struct vnode *vp; 684 struct uio *uio; 685 struct ucred *cred; 686 { 687 int error; 688 689 if (VTOFDESC(vp)->fd_type == Flink) { 690 char *ln = VTOFDESC(vp)->fd_link; 691 error = uiomove(ln, strlen(ln), uio); 692 } else { 693 error = EOPNOTSUPP; 694 } 695 696 return (error); 697 } 698 699 fdesc_read(vp, uio, ioflag, cred) 700 struct vnode *vp; 701 struct uio *uio; 702 int ioflag; 703 struct ucred *cred; 704 { 705 int error = EOPNOTSUPP; 706 707 switch (VTOFDESC(vp)->fd_type) { 708 case Fctty: 709 error = cttyread(devctty, uio, ioflag); 710 break; 711 712 default: 713 error = EOPNOTSUPP; 714 break; 715 } 716 717 return (error); 718 } 719 720 fdesc_write(vp, uio, ioflag, cred) 721 struct vnode *vp; 722 struct uio *uio; 723 int ioflag; 724 struct ucred *cred; 725 { 726 int error = EOPNOTSUPP; 727 728 switch (VTOFDESC(vp)->fd_type) { 729 case Fctty: 730 error = cttywrite(devctty, uio, ioflag); 731 break; 732 733 default: 734 error = EOPNOTSUPP; 735 break; 736 } 737 738 return (error); 739 } 740 741 fdesc_ioctl(vp, command, data, fflag, cred, p) 742 struct vnode *vp; 743 int command; 744 caddr_t data; 745 int fflag; 746 struct ucred *cred; 747 struct proc *p; 748 { 749 int error = EOPNOTSUPP; 750 751 #ifdef FDESC_DIAGNOSTIC 752 printf("fdesc_ioctl: type = %d, command = %x\n", 753 VTOFDESC(vp)->fd_type, command); 754 #endif 755 switch (VTOFDESC(vp)->fd_type) { 756 case Fctty: 757 error = cttyioctl(devctty, command, data, fflag, p); 758 break; 759 760 default: 761 error = EOPNOTSUPP; 762 break; 763 } 764 765 return (error); 766 } 767 768 fdesc_select(vp, which, fflags, cred, p) 769 struct vnode *vp; 770 int which; 771 int fflags; 772 struct ucred *cred; 773 struct proc *p; 774 { 775 int error = EOPNOTSUPP; 776 777 switch (VTOFDESC(vp)->fd_type) { 778 case Fctty: 779 error = cttyselect(devctty, fflags, p); 780 break; 781 782 default: 783 error = EOPNOTSUPP; 784 break; 785 } 786 787 return (error); 788 789 } 790 791 fdesc_inactive(vp, p) 792 struct vnode *vp; 793 struct proc *p; 794 { 795 /* 796 * Clear out the v_type field to avoid 797 * nasty things happening in vgone(). 798 */ 799 vp->v_type = VNON; 800 #ifdef FDESC_DIAGNOSTIC 801 printf("fdesc_inactive(%x)\n", vp); 802 #endif 803 return (0); 804 } 805 806 int fdesc_reclaim(vp) 807 struct vnode *vp; 808 { 809 int ix; 810 811 #ifdef FDESC_DIAGNOSTIC 812 printf("fdesc_reclaim(%x)\n", vp); 813 #endif 814 815 ix = VTOFDESC(vp)->fd_ix; 816 if (ix >= 0 && ix < FD_MAX && ix != FD_ROOT) { 817 if (fdescvp[ix] != vp) 818 panic("fdesc_reclaim"); 819 fdescvp[ix] = 0; 820 } 821 return (0); 822 } 823 824 /* 825 * Print out the contents of a /dev/fd vnode. 826 */ 827 /* ARGSUSED */ 828 fdesc_print(vp) 829 struct vnode *vp; 830 { 831 printf("tag VT_NON, fdesc vnode\n"); 832 } 833 834 /* 835 * /dev/fd vnode unsupported operation 836 */ 837 fdesc_enotsupp() 838 { 839 return (EOPNOTSUPP); 840 } 841 842 /* 843 * /dev/fd "should never get here" operation 844 */ 845 fdesc_badop() 846 { 847 panic("fdesc: bad op"); 848 /* NOTREACHED */ 849 } 850 851 /* 852 * /dev/fd vnode null operation 853 */ 854 fdesc_nullop() 855 { 856 return (0); 857 } 858 859 #define fdesc_create ((int (*) __P(( \ 860 struct nameidata *ndp, \ 861 struct vattr *vap, \ 862 struct proc *p))) fdesc_enotsupp) 863 #define fdesc_mknod ((int (*) __P(( \ 864 struct nameidata *ndp, \ 865 struct vattr *vap, \ 866 struct ucred *cred, \ 867 struct proc *p))) fdesc_enotsupp) 868 #define fdesc_close ((int (*) __P(( \ 869 struct vnode *vp, \ 870 int fflag, \ 871 struct ucred *cred, \ 872 struct proc *p))) nullop) 873 #define fdesc_access ((int (*) __P(( \ 874 struct vnode *vp, \ 875 int mode, \ 876 struct ucred *cred, \ 877 struct proc *p))) nullop) 878 #define fdesc_mmap ((int (*) __P(( \ 879 struct vnode *vp, \ 880 int fflags, \ 881 struct ucred *cred, \ 882 struct proc *p))) fdesc_enotsupp) 883 #define fdesc_fsync ((int (*) __P(( \ 884 struct vnode *vp, \ 885 int fflags, \ 886 struct ucred *cred, \ 887 int waitfor, \ 888 struct proc *p))) nullop) 889 #define fdesc_seek ((int (*) __P(( \ 890 struct vnode *vp, \ 891 off_t oldoff, \ 892 off_t newoff, \ 893 struct ucred *cred))) nullop) 894 #define fdesc_remove ((int (*) __P(( \ 895 struct nameidata *ndp, \ 896 struct proc *p))) fdesc_enotsupp) 897 #define fdesc_link ((int (*) __P(( \ 898 struct vnode *vp, \ 899 struct nameidata *ndp, \ 900 struct proc *p))) fdesc_enotsupp) 901 #define fdesc_rename ((int (*) __P(( \ 902 struct nameidata *fndp, \ 903 struct nameidata *tdnp, \ 904 struct proc *p))) fdesc_enotsupp) 905 #define fdesc_mkdir ((int (*) __P(( \ 906 struct nameidata *ndp, \ 907 struct vattr *vap, \ 908 struct proc *p))) fdesc_enotsupp) 909 #define fdesc_rmdir ((int (*) __P(( \ 910 struct nameidata *ndp, \ 911 struct proc *p))) fdesc_enotsupp) 912 #define fdesc_symlink ((int (*) __P(( \ 913 struct nameidata *ndp, \ 914 struct vattr *vap, \ 915 char *target, \ 916 struct proc *p))) fdesc_enotsupp) 917 #define fdesc_abortop ((int (*) __P(( \ 918 struct nameidata *ndp))) nullop) 919 #define fdesc_lock ((int (*) __P(( \ 920 struct vnode *vp))) nullop) 921 #define fdesc_unlock ((int (*) __P(( \ 922 struct vnode *vp))) nullop) 923 #define fdesc_bmap ((int (*) __P(( \ 924 struct vnode *vp, \ 925 daddr_t bn, \ 926 struct vnode **vpp, \ 927 daddr_t *bnp))) fdesc_badop) 928 #define fdesc_strategy ((int (*) __P(( \ 929 struct buf *bp))) fdesc_badop) 930 #define fdesc_islocked ((int (*) __P(( \ 931 struct vnode *vp))) nullop) 932 #define fdesc_advlock ((int (*) __P(( \ 933 struct vnode *vp, \ 934 caddr_t id, \ 935 int op, \ 936 struct flock *fl, \ 937 int flags))) fdesc_enotsupp) 938 939 struct vnodeops fdesc_vnodeops = { 940 fdesc_lookup, /* lookup */ 941 fdesc_create, /* create */ 942 fdesc_mknod, /* mknod */ 943 fdesc_open, /* open */ 944 fdesc_close, /* close */ 945 fdesc_access, /* access */ 946 fdesc_getattr, /* getattr */ 947 fdesc_setattr, /* setattr */ 948 fdesc_read, /* read */ 949 fdesc_write, /* write */ 950 fdesc_ioctl, /* ioctl */ 951 fdesc_select, /* select */ 952 fdesc_mmap, /* mmap */ 953 fdesc_fsync, /* fsync */ 954 fdesc_seek, /* seek */ 955 fdesc_remove, /* remove */ 956 fdesc_link, /* link */ 957 fdesc_rename, /* rename */ 958 fdesc_mkdir, /* mkdir */ 959 fdesc_rmdir, /* rmdir */ 960 fdesc_symlink, /* symlink */ 961 fdesc_readdir, /* readdir */ 962 fdesc_readlink, /* readlink */ 963 fdesc_abortop, /* abortop */ 964 fdesc_inactive, /* inactive */ 965 fdesc_reclaim, /* reclaim */ 966 fdesc_lock, /* lock */ 967 fdesc_unlock, /* unlock */ 968 fdesc_bmap, /* bmap */ 969 fdesc_strategy, /* strategy */ 970 fdesc_print, /* print */ 971 fdesc_islocked, /* islocked */ 972 fdesc_advlock, /* advlock */ 973 }; 974