|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * Copyright (c) 1992, 1993 ! 28: * The Regents of the University of California. All rights reserved. ! 29: * ! 30: * This code is derived from software donated to Berkeley by ! 31: * Jan-Simon Pendry. ! 32: * ! 33: * Redistribution and use in source and binary forms, with or without ! 34: * modification, are permitted provided that the following conditions ! 35: * are met: ! 36: * 1. Redistributions of source code must retain the above copyright ! 37: * notice, this list of conditions and the following disclaimer. ! 38: * 2. Redistributions in binary form must reproduce the above copyright ! 39: * notice, this list of conditions and the following disclaimer in the ! 40: * documentation and/or other materials provided with the distribution. ! 41: * 3. All advertising materials mentioning features or use of this software ! 42: * must display the following acknowledgement: ! 43: * This product includes software developed by the University of ! 44: * California, Berkeley and its contributors. ! 45: * 4. Neither the name of the University nor the names of its contributors ! 46: * may be used to endorse or promote products derived from this software ! 47: * without specific prior written permission. ! 48: * ! 49: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 50: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 51: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 52: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 53: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 54: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 55: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 56: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 57: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 58: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 59: * SUCH DAMAGE. ! 60: * ! 61: * @(#)fdesc_vnops.c 8.17 (Berkeley) 5/22/95 ! 62: * ! 63: */ ! 64: ! 65: /* ! 66: * /dev/fd Filesystem ! 67: */ ! 68: ! 69: #include <sys/param.h> ! 70: #include <sys/systm.h> ! 71: #include <sys/types.h> ! 72: #include <sys/time.h> ! 73: #include <sys/proc.h> ! 74: #include <sys/kernel.h> /* boottime */ ! 75: #include <sys/resourcevar.h> ! 76: #include <sys/filedesc.h> ! 77: #include <sys/vnode.h> ! 78: #include <sys/malloc.h> ! 79: #include <sys/file.h> ! 80: #include <sys/stat.h> ! 81: #include <sys/mount.h> ! 82: #include <sys/namei.h> ! 83: #include <sys/buf.h> ! 84: #include <sys/dirent.h> ! 85: #include <miscfs/fdesc/fdesc.h> ! 86: ! 87: #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL) ! 88: ! 89: #define FDL_WANT 0x01 ! 90: #define FDL_LOCKED 0x02 ! 91: static int fdcache_lock; ! 92: ! 93: dev_t devctty; ! 94: ! 95: #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1) ! 96: FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2 ! 97: #endif ! 98: ! 99: #define NFDCACHE 4 ! 100: ! 101: #define FD_NHASH(ix) \ ! 102: (&fdhashtbl[(ix) & fdhash]) ! 103: LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl; ! 104: u_long fdhash; ! 105: ! 106: /* ! 107: * Initialise cache headers ! 108: */ ! 109: fdesc_init(vfsp) ! 110: struct vfsconf *vfsp; ! 111: { ! 112: ! 113: devctty = makedev(nchrdev, 0); ! 114: fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash); ! 115: } ! 116: ! 117: int ! 118: fdesc_allocvp(ftype, ix, mp, vpp) ! 119: fdntype ftype; ! 120: int ix; ! 121: struct mount *mp; ! 122: struct vnode **vpp; ! 123: { ! 124: struct proc *p = current_proc(); /* XXX */ ! 125: struct fdhashhead *fc; ! 126: struct fdescnode *fd; ! 127: int error = 0; ! 128: ! 129: fc = FD_NHASH(ix); ! 130: loop: ! 131: for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) { ! 132: if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { ! 133: if (vget(fd->fd_vnode, 0, p)) ! 134: goto loop; ! 135: *vpp = fd->fd_vnode; ! 136: return (error); ! 137: } ! 138: } ! 139: ! 140: /* ! 141: * otherwise lock the array while we call getnewvnode ! 142: * since that can block. ! 143: */ ! 144: if (fdcache_lock & FDL_LOCKED) { ! 145: fdcache_lock |= FDL_WANT; ! 146: sleep((caddr_t) &fdcache_lock, PINOD); ! 147: goto loop; ! 148: } ! 149: fdcache_lock |= FDL_LOCKED; ! 150: ! 151: error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp); ! 152: if (error) ! 153: goto out; ! 154: MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); ! 155: (*vpp)->v_data = fd; ! 156: fd->fd_vnode = *vpp; ! 157: fd->fd_type = ftype; ! 158: fd->fd_fd = -1; ! 159: fd->fd_link = 0; ! 160: fd->fd_ix = ix; ! 161: LIST_INSERT_HEAD(fc, fd, fd_hash); ! 162: ! 163: out:; ! 164: fdcache_lock &= ~FDL_LOCKED; ! 165: ! 166: if (fdcache_lock & FDL_WANT) { ! 167: fdcache_lock &= ~FDL_WANT; ! 168: wakeup((caddr_t) &fdcache_lock); ! 169: } ! 170: ! 171: return (error); ! 172: } ! 173: ! 174: /* ! 175: * vp is the current namei directory ! 176: * ndp is the name to locate in that directory... ! 177: */ ! 178: int ! 179: fdesc_lookup(ap) ! 180: struct vop_lookup_args /* { ! 181: struct vnode * a_dvp; ! 182: struct vnode ** a_vpp; ! 183: struct componentname * a_cnp; ! 184: } */ *ap; ! 185: { ! 186: struct vnode **vpp = ap->a_vpp; ! 187: struct vnode *dvp = ap->a_dvp; ! 188: struct componentname *cnp = ap->a_cnp; ! 189: char *pname = cnp->cn_nameptr; ! 190: struct proc *p = cnp->cn_proc; ! 191: int nfiles = p->p_fd->fd_nfiles; ! 192: unsigned fd; ! 193: int error; ! 194: struct vnode *fvp; ! 195: char *ln; ! 196: ! 197: VOP_UNLOCK(dvp, 0, p); ! 198: if (cnp->cn_namelen == 1 && *pname == '.') { ! 199: *vpp = dvp; ! 200: VREF(dvp); ! 201: vn_lock(dvp, LK_SHARED | LK_RETRY, p); ! 202: return (0); ! 203: } ! 204: ! 205: switch (VTOFDESC(dvp)->fd_type) { ! 206: default: ! 207: case Flink: ! 208: case Fdesc: ! 209: case Fctty: ! 210: error = ENOTDIR; ! 211: goto bad; ! 212: ! 213: case Froot: ! 214: if (cnp->cn_namelen == 2 && bcmp(pname, "fd", 2) == 0) { ! 215: error = fdesc_allocvp(Fdevfd, FD_DEVFD, dvp->v_mount, &fvp); ! 216: if (error) ! 217: goto bad; ! 218: *vpp = fvp; ! 219: fvp->v_type = VDIR; ! 220: vn_lock(fvp, LK_SHARED | LK_RETRY, p); ! 221: return (0); ! 222: } ! 223: ! 224: if (cnp->cn_namelen == 3 && bcmp(pname, "tty", 3) == 0) { ! 225: struct vnode *ttyvp = cttyvp(p); ! 226: if (ttyvp == NULL) { ! 227: error = ENXIO; ! 228: goto bad; ! 229: } ! 230: error = fdesc_allocvp(Fctty, FD_CTTY, dvp->v_mount, &fvp); ! 231: if (error) ! 232: goto bad; ! 233: *vpp = fvp; ! 234: fvp->v_type = VFIFO; ! 235: vn_lock(fvp, LK_SHARED | LK_RETRY, p); ! 236: return (0); ! 237: } ! 238: ! 239: ln = 0; ! 240: switch (cnp->cn_namelen) { ! 241: case 5: ! 242: if (bcmp(pname, "stdin", 5) == 0) { ! 243: ln = "fd/0"; ! 244: fd = FD_STDIN; ! 245: } ! 246: break; ! 247: case 6: ! 248: if (bcmp(pname, "stdout", 6) == 0) { ! 249: ln = "fd/1"; ! 250: fd = FD_STDOUT; ! 251: } else ! 252: if (bcmp(pname, "stderr", 6) == 0) { ! 253: ln = "fd/2"; ! 254: fd = FD_STDERR; ! 255: } ! 256: break; ! 257: } ! 258: ! 259: if (ln) { ! 260: error = fdesc_allocvp(Flink, fd, dvp->v_mount, &fvp); ! 261: if (error) ! 262: goto bad; ! 263: VTOFDESC(fvp)->fd_link = ln; ! 264: *vpp = fvp; ! 265: fvp->v_type = VLNK; ! 266: vn_lock(fvp, LK_SHARED | LK_RETRY, p); ! 267: return (0); ! 268: } else { ! 269: error = ENOENT; ! 270: goto bad; ! 271: } ! 272: ! 273: /* FALL THROUGH */ ! 274: ! 275: case Fdevfd: ! 276: if (cnp->cn_namelen == 2 && bcmp(pname, "..", 2) == 0) { ! 277: if (error = fdesc_root(dvp->v_mount, vpp)) ! 278: goto bad; ! 279: return (0); ! 280: } ! 281: ! 282: fd = 0; ! 283: while (*pname >= '0' && *pname <= '9') { ! 284: fd = 10 * fd + *pname++ - '0'; ! 285: if (fd >= nfiles) ! 286: break; ! 287: } ! 288: ! 289: if (*pname != '\0') { ! 290: error = ENOENT; ! 291: goto bad; ! 292: } ! 293: ! 294: if (fd >= nfiles || ! 295: *fdfile(p, fd) == NULL || ! 296: (*fdflags(p, fd) & UF_RESERVED)) { ! 297: error = EBADF; ! 298: goto bad; ! 299: } ! 300: ! 301: error = fdesc_allocvp(Fdesc, FD_DESC+fd, dvp->v_mount, &fvp); ! 302: if (error) ! 303: goto bad; ! 304: VTOFDESC(fvp)->fd_fd = fd; ! 305: vn_lock(fvp, LK_SHARED | LK_RETRY, p); ! 306: *vpp = fvp; ! 307: return (0); ! 308: } ! 309: ! 310: bad:; ! 311: vn_lock(dvp, LK_SHARED | LK_RETRY, p); ! 312: *vpp = NULL; ! 313: return (error); ! 314: } ! 315: ! 316: int ! 317: fdesc_open(ap) ! 318: struct vop_open_args /* { ! 319: struct vnode *a_vp; ! 320: int a_mode; ! 321: struct ucred *a_cred; ! 322: struct proc *a_p; ! 323: } */ *ap; ! 324: { ! 325: struct vnode *vp = ap->a_vp; ! 326: int error = 0; ! 327: ! 328: switch (VTOFDESC(vp)->fd_type) { ! 329: case Fdesc: ! 330: /* ! 331: * XXX Kludge: set p->p_dupfd to contain the value of the ! 332: * the file descriptor being sought for duplication. The error ! 333: * return ensures that the vnode for this device will be ! 334: * released by vn_open. Open will detect this special error and ! 335: * take the actions in dupfdopen. Other callers of vn_open or ! 336: * VOP_OPEN will simply report the error. ! 337: */ ! 338: ap->a_p->p_dupfd = VTOFDESC(vp)->fd_fd; /* XXX */ ! 339: error = ENODEV; ! 340: break; ! 341: ! 342: case Fctty: ! 343: error = cttyopen(devctty, ap->a_mode, 0, ap->a_p); ! 344: break; ! 345: } ! 346: ! 347: return (error); ! 348: } ! 349: ! 350: static int ! 351: fdesc_attr(fd, vap, cred, p) ! 352: int fd; ! 353: struct vattr *vap; ! 354: struct ucred *cred; ! 355: struct proc *p; ! 356: { ! 357: struct file *fp; ! 358: struct stat stb; ! 359: int error; ! 360: ! 361: if (error = fdgetf(p, fd, &fp)) ! 362: return (error); ! 363: switch (fp->f_type) { ! 364: case DTYPE_VNODE: ! 365: error = VOP_GETATTR((struct vnode *) fp->f_data, vap, cred, p); ! 366: if (error == 0 && vap->va_type == VDIR) { ! 367: /* ! 368: * directories can cause loops in the namespace, ! 369: * so turn off the 'x' bits to avoid trouble. ! 370: */ ! 371: vap->va_mode &= ~((VEXEC)|(VEXEC>>3)|(VEXEC>>6)); ! 372: } ! 373: break; ! 374: ! 375: case DTYPE_SOCKET: ! 376: error = soo_stat((struct socket *)fp->f_data, &stb); ! 377: if (error == 0) { ! 378: vattr_null(vap); ! 379: vap->va_type = VSOCK; ! 380: vap->va_mode = stb.st_mode; ! 381: vap->va_nlink = stb.st_nlink; ! 382: vap->va_uid = stb.st_uid; ! 383: vap->va_gid = stb.st_gid; ! 384: vap->va_fsid = stb.st_dev; ! 385: vap->va_fileid = stb.st_ino; ! 386: vap->va_size = stb.st_size; ! 387: vap->va_blocksize = stb.st_blksize; ! 388: vap->va_atime = stb.st_atimespec; ! 389: vap->va_mtime = stb.st_mtimespec; ! 390: vap->va_ctime = stb.st_ctimespec; ! 391: vap->va_gen = stb.st_gen; ! 392: vap->va_flags = stb.st_flags; ! 393: vap->va_rdev = stb.st_rdev; ! 394: vap->va_bytes = stb.st_blocks * stb.st_blksize; ! 395: } ! 396: break; ! 397: ! 398: default: ! 399: panic("fdesc attr"); ! 400: break; ! 401: } ! 402: ! 403: return (error); ! 404: } ! 405: ! 406: int ! 407: fdesc_getattr(ap) ! 408: struct vop_getattr_args /* { ! 409: struct vnode *a_vp; ! 410: struct vattr *a_vap; ! 411: struct ucred *a_cred; ! 412: struct proc *a_p; ! 413: } */ *ap; ! 414: { ! 415: struct vnode *vp = ap->a_vp; ! 416: struct vattr *vap = ap->a_vap; ! 417: unsigned fd; ! 418: int error = 0; ! 419: ! 420: switch (VTOFDESC(vp)->fd_type) { ! 421: case Froot: ! 422: case Fdevfd: ! 423: case Flink: ! 424: case Fctty: ! 425: bzero((caddr_t) vap, sizeof(*vap)); ! 426: vattr_null(vap); ! 427: vap->va_fileid = VTOFDESC(vp)->fd_ix; ! 428: ! 429: switch (VTOFDESC(vp)->fd_type) { ! 430: case Flink: ! 431: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; ! 432: vap->va_type = VLNK; ! 433: vap->va_nlink = 1; ! 434: vap->va_size = strlen(VTOFDESC(vp)->fd_link); ! 435: break; ! 436: ! 437: case Fctty: ! 438: vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; ! 439: vap->va_type = VFIFO; ! 440: vap->va_nlink = 1; ! 441: vap->va_size = 0; ! 442: break; ! 443: ! 444: default: ! 445: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; ! 446: vap->va_type = VDIR; ! 447: vap->va_nlink = 2; ! 448: vap->va_size = DEV_BSIZE; ! 449: break; ! 450: } ! 451: vap->va_uid = 0; ! 452: vap->va_gid = 0; ! 453: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; ! 454: vap->va_blocksize = DEV_BSIZE; ! 455: vap->va_atime.tv_sec = boottime.tv_sec; ! 456: vap->va_atime.tv_nsec = 0; ! 457: vap->va_mtime = vap->va_atime; ! 458: vap->va_ctime = vap->va_mtime; ! 459: vap->va_gen = 0; ! 460: vap->va_flags = 0; ! 461: vap->va_rdev = 0; ! 462: vap->va_bytes = 0; ! 463: break; ! 464: ! 465: case Fdesc: ! 466: fd = VTOFDESC(vp)->fd_fd; ! 467: error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p); ! 468: break; ! 469: ! 470: default: ! 471: panic("fdesc_getattr"); ! 472: break; ! 473: } ! 474: ! 475: if (error == 0) ! 476: vp->v_type = vap->va_type; ! 477: ! 478: return (error); ! 479: } ! 480: ! 481: int ! 482: fdesc_setattr(ap) ! 483: struct vop_setattr_args /* { ! 484: struct vnode *a_vp; ! 485: struct vattr *a_vap; ! 486: struct ucred *a_cred; ! 487: struct proc *a_p; ! 488: } */ *ap; ! 489: { ! 490: struct file *fp; ! 491: unsigned fd; ! 492: int error; ! 493: ! 494: /* ! 495: * Can't mess with the root vnode ! 496: */ ! 497: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 498: case Fdesc: ! 499: break; ! 500: ! 501: case Fctty: ! 502: return (0); ! 503: ! 504: default: ! 505: return (EACCES); ! 506: } ! 507: ! 508: fd = VTOFDESC(ap->a_vp)->fd_fd; ! 509: if (error = fdgetf(ap->a_p, fd, &fp)) ! 510: return (error); ! 511: ! 512: /* ! 513: * Can setattr the underlying vnode, but not sockets! ! 514: */ ! 515: switch (fp->f_type) { ! 516: case DTYPE_VNODE: ! 517: error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p); ! 518: break; ! 519: ! 520: case DTYPE_SOCKET: ! 521: error = 0; ! 522: break; ! 523: ! 524: default: ! 525: kprintf("fp->f_type = %d\n", fp->f_type); ! 526: error = EBADF; ! 527: break; ! 528: } ! 529: ! 530: return (error); ! 531: } ! 532: ! 533: #define UIO_MX 16 ! 534: ! 535: static struct dirtmp { ! 536: u_long d_fileno; ! 537: u_short d_reclen; ! 538: u_short d_namlen; ! 539: char d_name[8]; ! 540: } rootent[] = { ! 541: { FD_DEVFD, UIO_MX, 2, "fd" }, ! 542: { FD_STDIN, UIO_MX, 5, "stdin" }, ! 543: { FD_STDOUT, UIO_MX, 6, "stdout" }, ! 544: { FD_STDERR, UIO_MX, 6, "stderr" }, ! 545: { FD_CTTY, UIO_MX, 3, "tty" }, ! 546: { 0 } ! 547: }; ! 548: ! 549: int ! 550: fdesc_readdir(ap) ! 551: struct vop_readdir_args /* { ! 552: struct vnode *a_vp; ! 553: struct uio *a_uio; ! 554: struct ucred *a_cred; ! 555: int *a_eofflag; ! 556: u_long *a_cookies; ! 557: int a_ncookies; ! 558: } */ *ap; ! 559: { ! 560: struct uio *uio = ap->a_uio; ! 561: struct proc *p = uio->uio_procp; ! 562: int i, error; ! 563: ! 564: /* ! 565: * We don't allow exporting fdesc mounts, and currently local ! 566: * requests do not need cookies. ! 567: */ ! 568: if (ap->a_ncookies) ! 569: panic("fdesc_readdir: not hungry"); ! 570: ! 571: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 572: case Fctty: ! 573: return (0); ! 574: ! 575: case Fdesc: ! 576: return (ENOTDIR); ! 577: ! 578: default: ! 579: break; ! 580: } ! 581: ! 582: if (VTOFDESC(ap->a_vp)->fd_type == Froot) { ! 583: struct dirent d; ! 584: struct dirent *dp = &d; ! 585: struct dirtmp *dt; ! 586: int fd; ! 587: ! 588: i = uio->uio_offset / UIO_MX; ! 589: error = 0; ! 590: ! 591: while (uio->uio_resid > 0) { ! 592: dt = &rootent[i]; ! 593: if (dt->d_fileno == 0) { ! 594: /**eofflagp = 1;*/ ! 595: break; ! 596: } ! 597: i++; ! 598: ! 599: switch (dt->d_fileno) { ! 600: case FD_CTTY: ! 601: if (cttyvp(uio->uio_procp) == NULL) ! 602: continue; ! 603: break; ! 604: ! 605: case FD_STDIN: ! 606: case FD_STDOUT: ! 607: case FD_STDERR: ! 608: fd = dt->d_fileno - FD_STDIN; ! 609: if (fd >= p->p_fd->fd_nfiles) ! 610: continue; ! 611: if (*fdfile(p, fd) == NULL && ! 612: !(*fdflags(p, fd) & ! 613: UF_RESERVED)) ! 614: continue; ! 615: break; ! 616: } ! 617: bzero((caddr_t) dp, UIO_MX); ! 618: dp->d_fileno = dt->d_fileno; ! 619: dp->d_namlen = dt->d_namlen; ! 620: dp->d_type = DT_UNKNOWN; ! 621: dp->d_reclen = dt->d_reclen; ! 622: bcopy(dt->d_name, dp->d_name, dp->d_namlen+1); ! 623: error = uiomove((caddr_t) dp, UIO_MX, uio); ! 624: if (error) ! 625: break; ! 626: } ! 627: uio->uio_offset = i * UIO_MX; ! 628: return (error); ! 629: } ! 630: ! 631: i = uio->uio_offset / UIO_MX; ! 632: error = 0; ! 633: while (uio->uio_resid > 0) { ! 634: if (i >= p->p_fd->fd_nfiles) ! 635: break; ! 636: ! 637: if (*fdfile(p, i) != NULL && !(*fdflags(p, i) & UF_RESERVED)) { ! 638: struct dirent d; ! 639: struct dirent *dp = &d; ! 640: ! 641: bzero((caddr_t) dp, UIO_MX); ! 642: ! 643: dp->d_namlen = sprintf(dp->d_name, "%d", i); ! 644: dp->d_reclen = UIO_MX; ! 645: dp->d_type = DT_UNKNOWN; ! 646: dp->d_fileno = i + FD_STDIN; ! 647: /* ! 648: * And ship to userland ! 649: */ ! 650: error = uiomove((caddr_t) dp, UIO_MX, uio); ! 651: if (error) ! 652: break; ! 653: } ! 654: i++; ! 655: } ! 656: ! 657: uio->uio_offset = i * UIO_MX; ! 658: return (error); ! 659: } ! 660: ! 661: int ! 662: fdesc_readlink(ap) ! 663: struct vop_readlink_args /* { ! 664: struct vnode *a_vp; ! 665: struct uio *a_uio; ! 666: struct ucred *a_cred; ! 667: } */ *ap; ! 668: { ! 669: struct vnode *vp = ap->a_vp; ! 670: int error; ! 671: ! 672: if (vp->v_type != VLNK) ! 673: return (EPERM); ! 674: ! 675: if (VTOFDESC(vp)->fd_type == Flink) { ! 676: char *ln = VTOFDESC(vp)->fd_link; ! 677: error = uiomove(ln, strlen(ln), ap->a_uio); ! 678: } else { ! 679: error = EOPNOTSUPP; ! 680: } ! 681: ! 682: return (error); ! 683: } ! 684: ! 685: int ! 686: fdesc_read(ap) ! 687: struct vop_read_args /* { ! 688: struct vnode *a_vp; ! 689: struct uio *a_uio; ! 690: int a_ioflag; ! 691: struct ucred *a_cred; ! 692: } */ *ap; ! 693: { ! 694: int error = EOPNOTSUPP; ! 695: ! 696: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 697: case Fctty: ! 698: error = cttyread(devctty, ap->a_uio, ap->a_ioflag); ! 699: break; ! 700: ! 701: default: ! 702: error = EOPNOTSUPP; ! 703: break; ! 704: } ! 705: ! 706: return (error); ! 707: } ! 708: ! 709: int ! 710: fdesc_write(ap) ! 711: struct vop_write_args /* { ! 712: struct vnode *a_vp; ! 713: struct uio *a_uio; ! 714: int a_ioflag; ! 715: struct ucred *a_cred; ! 716: } */ *ap; ! 717: { ! 718: int error = EOPNOTSUPP; ! 719: ! 720: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 721: case Fctty: ! 722: error = cttywrite(devctty, ap->a_uio, ap->a_ioflag); ! 723: break; ! 724: ! 725: default: ! 726: error = EOPNOTSUPP; ! 727: break; ! 728: } ! 729: ! 730: return (error); ! 731: } ! 732: ! 733: int ! 734: fdesc_ioctl(ap) ! 735: struct vop_ioctl_args /* { ! 736: struct vnode *a_vp; ! 737: int a_command; ! 738: caddr_t a_data; ! 739: int a_fflag; ! 740: struct ucred *a_cred; ! 741: struct proc *a_p; ! 742: } */ *ap; ! 743: { ! 744: int error = EOPNOTSUPP; ! 745: ! 746: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 747: case Fctty: ! 748: error = cttyioctl(devctty, ap->a_command, ap->a_data, ! 749: ap->a_fflag, ap->a_p); ! 750: break; ! 751: ! 752: default: ! 753: error = EOPNOTSUPP; ! 754: break; ! 755: } ! 756: ! 757: return (error); ! 758: } ! 759: ! 760: int ! 761: fdesc_select(ap) ! 762: struct vop_select_args /* { ! 763: struct vnode *a_vp; ! 764: int a_which; ! 765: int a_fflags; ! 766: struct ucred *a_cred; ! 767: struct proc *a_p; ! 768: } */ *ap; ! 769: { ! 770: int error = EOPNOTSUPP; ! 771: ! 772: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 773: case Fctty: ! 774: error = cttyselect(devctty, ap->a_fflags, ap->a_p); ! 775: break; ! 776: ! 777: default: ! 778: error = EOPNOTSUPP; ! 779: break; ! 780: } ! 781: ! 782: return (error); ! 783: } ! 784: ! 785: int ! 786: fdesc_inactive(ap) ! 787: struct vop_inactive_args /* { ! 788: struct vnode *a_vp; ! 789: struct proc *a_p; ! 790: } */ *ap; ! 791: { ! 792: struct vnode *vp = ap->a_vp; ! 793: ! 794: /* ! 795: * Clear out the v_type field to avoid ! 796: * nasty things happening in vgone(). ! 797: */ ! 798: VOP_UNLOCK(vp, 0, ap->a_p); ! 799: vp->v_type = VNON; ! 800: return (0); ! 801: } ! 802: ! 803: int ! 804: fdesc_reclaim(ap) ! 805: struct vop_reclaim_args /* { ! 806: struct vnode *a_vp; ! 807: } */ *ap; ! 808: { ! 809: struct vnode *vp = ap->a_vp; ! 810: struct fdescnode *fd = VTOFDESC(vp); ! 811: ! 812: LIST_REMOVE(fd, fd_hash); ! 813: FREE(vp->v_data, M_TEMP); ! 814: vp->v_data = 0; ! 815: ! 816: return (0); ! 817: } ! 818: ! 819: /* ! 820: * Return POSIX pathconf information applicable to special devices. ! 821: */ ! 822: fdesc_pathconf(ap) ! 823: struct vop_pathconf_args /* { ! 824: struct vnode *a_vp; ! 825: int a_name; ! 826: int *a_retval; ! 827: } */ *ap; ! 828: { ! 829: ! 830: switch (ap->a_name) { ! 831: case _PC_LINK_MAX: ! 832: *ap->a_retval = LINK_MAX; ! 833: return (0); ! 834: case _PC_MAX_CANON: ! 835: *ap->a_retval = MAX_CANON; ! 836: return (0); ! 837: case _PC_MAX_INPUT: ! 838: *ap->a_retval = MAX_INPUT; ! 839: return (0); ! 840: case _PC_PIPE_BUF: ! 841: *ap->a_retval = PIPE_BUF; ! 842: return (0); ! 843: case _PC_CHOWN_RESTRICTED: ! 844: *ap->a_retval = 1; ! 845: return (0); ! 846: case _PC_VDISABLE: ! 847: *ap->a_retval = _POSIX_VDISABLE; ! 848: return (0); ! 849: default: ! 850: return (EINVAL); ! 851: } ! 852: /* NOTREACHED */ ! 853: } ! 854: ! 855: /* ! 856: * Print out the contents of a /dev/fd vnode. ! 857: */ ! 858: /* ARGSUSED */ ! 859: int ! 860: fdesc_print(ap) ! 861: struct vop_print_args /* { ! 862: struct vnode *a_vp; ! 863: } */ *ap; ! 864: { ! 865: ! 866: printf("tag VT_NON, fdesc vnode\n"); ! 867: return (0); ! 868: } ! 869: ! 870: /*void*/ ! 871: int ! 872: fdesc_vfree(ap) ! 873: struct vop_vfree_args /* { ! 874: struct vnode *a_pvp; ! 875: ino_t a_ino; ! 876: int a_mode; ! 877: } */ *ap; ! 878: { ! 879: ! 880: return (0); ! 881: } ! 882: ! 883: /* ! 884: * /dev/fd "should never get here" operation ! 885: */ ! 886: int ! 887: fdesc_badop() ! 888: { ! 889: ! 890: panic("fdesc: bad op"); ! 891: /* NOTREACHED */ ! 892: } ! 893: ! 894: /* Pagein */ ! 895: fdesc_pagein(ap) ! 896: struct vop_pagein_args /* { ! 897: struct vnode *a_vp; ! 898: struct uio *a_uio; ! 899: int a_ioflag; ! 900: struct ucred *a_cred; ! 901: } */ *ap; ! 902: { ! 903: /* pass thru to read */ ! 904: return (VOP_READ(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); ! 905: } ! 906: ! 907: /* Pageout */ ! 908: fdesc_pageout(ap) ! 909: struct vop_pageout_args /* { ! 910: struct vnode *a_vp; ! 911: struct uio *a_uio; ! 912: int a_ioflag; ! 913: struct ucred *a_cred; ! 914: } */ *ap; ! 915: { ! 916: /* pass thru to write */ ! 917: return (VOP_WRITE(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); ! 918: } ! 919: ! 920: #define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp) ! 921: #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp) ! 922: #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop) ! 923: #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop) ! 924: #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp) ! 925: #define fdesc_revoke vop_revoke ! 926: #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) ! 927: #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop) ! 928: #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp) ! 929: #define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp) ! 930: #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp) ! 931: #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp) ! 932: #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp) ! 933: #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp) ! 934: #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) ! 935: #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock) ! 936: #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock) ! 937: #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop) ! 938: #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop) ! 939: #define fdesc_islocked \ ! 940: ((int (*) __P((struct vop_islocked_args *)))vop_noislocked) ! 941: #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp) ! 942: #define fdesc_blkatoff \ ! 943: ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp) ! 944: #define fdesc_valloc ((int(*) __P(( \ ! 945: struct vnode *pvp, \ ! 946: int mode, \ ! 947: struct ucred *cred, \ ! 948: struct vnode **vpp))) eopnotsupp) ! 949: #define fdesc_truncate \ ! 950: ((int (*) __P((struct vop_truncate_args *)))eopnotsupp) ! 951: #define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp) ! 952: #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp) ! 953: ! 954: int (**fdesc_vnodeop_p)(); ! 955: struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = { ! 956: { &vop_default_desc, vn_default_error }, ! 957: { &vop_lookup_desc, fdesc_lookup }, /* lookup */ ! 958: { &vop_create_desc, fdesc_create }, /* create */ ! 959: { &vop_mknod_desc, fdesc_mknod }, /* mknod */ ! 960: { &vop_open_desc, fdesc_open }, /* open */ ! 961: { &vop_close_desc, fdesc_close }, /* close */ ! 962: { &vop_access_desc, fdesc_access }, /* access */ ! 963: { &vop_getattr_desc, fdesc_getattr }, /* getattr */ ! 964: { &vop_setattr_desc, fdesc_setattr }, /* setattr */ ! 965: { &vop_read_desc, fdesc_read }, /* read */ ! 966: { &vop_write_desc, fdesc_write }, /* write */ ! 967: { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */ ! 968: { &vop_select_desc, fdesc_select }, /* select */ ! 969: { &vop_revoke_desc, fdesc_revoke }, /* revoke */ ! 970: { &vop_mmap_desc, fdesc_mmap }, /* mmap */ ! 971: { &vop_fsync_desc, fdesc_fsync }, /* fsync */ ! 972: { &vop_seek_desc, fdesc_seek }, /* seek */ ! 973: { &vop_remove_desc, fdesc_remove }, /* remove */ ! 974: { &vop_link_desc, fdesc_link }, /* link */ ! 975: { &vop_rename_desc, fdesc_rename }, /* rename */ ! 976: { &vop_mkdir_desc, fdesc_mkdir }, /* mkdir */ ! 977: { &vop_rmdir_desc, fdesc_rmdir }, /* rmdir */ ! 978: { &vop_symlink_desc, fdesc_symlink }, /* symlink */ ! 979: { &vop_readdir_desc, fdesc_readdir }, /* readdir */ ! 980: { &vop_readlink_desc, fdesc_readlink }, /* readlink */ ! 981: { &vop_abortop_desc, fdesc_abortop }, /* abortop */ ! 982: { &vop_inactive_desc, fdesc_inactive }, /* inactive */ ! 983: { &vop_reclaim_desc, fdesc_reclaim }, /* reclaim */ ! 984: { &vop_lock_desc, fdesc_lock }, /* lock */ ! 985: { &vop_unlock_desc, fdesc_unlock }, /* unlock */ ! 986: { &vop_bmap_desc, fdesc_bmap }, /* bmap */ ! 987: { &vop_strategy_desc, fdesc_strategy }, /* strategy */ ! 988: { &vop_print_desc, fdesc_print }, /* print */ ! 989: { &vop_islocked_desc, fdesc_islocked }, /* islocked */ ! 990: { &vop_pathconf_desc, fdesc_pathconf }, /* pathconf */ ! 991: { &vop_advlock_desc, fdesc_advlock }, /* advlock */ ! 992: { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */ ! 993: { &vop_valloc_desc, fdesc_valloc }, /* valloc */ ! 994: { &vop_vfree_desc, fdesc_vfree }, /* vfree */ ! 995: { &vop_truncate_desc, fdesc_truncate }, /* truncate */ ! 996: { &vop_update_desc, fdesc_update }, /* update */ ! 997: { &vop_bwrite_desc, fdesc_bwrite }, /* bwrite */ ! 998: { &vop_bwrite_desc, fdesc_pagein }, /* pagein */ ! 999: { &vop_bwrite_desc, fdesc_pageout }, /* pageout */ ! 1000: { (struct vnodeop_desc*)NULL, (int(*)())NULL } ! 1001: }; ! 1002: struct vnodeopv_desc fdesc_vnodeop_opv_desc = ! 1003: { &fdesc_vnodeop_p, fdesc_vnodeop_entries };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.