|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 23: /* ! 24: * Copyright (c) 1992, 1993 ! 25: * The Regents of the University of California. All rights reserved. ! 26: * ! 27: * This code is derived from software donated to Berkeley by ! 28: * Jan-Simon Pendry. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)fdesc_vnops.c 8.17 (Berkeley) 5/22/95 ! 59: * ! 60: */ ! 61: ! 62: /* ! 63: * /dev/fd Filesystem ! 64: */ ! 65: ! 66: #include <sys/param.h> ! 67: #include <sys/systm.h> ! 68: #include <sys/types.h> ! 69: #include <sys/time.h> ! 70: #include <sys/proc.h> ! 71: #include <sys/kernel.h> /* boottime */ ! 72: #include <sys/resourcevar.h> ! 73: #include <sys/filedesc.h> ! 74: #include <sys/vnode.h> ! 75: #include <sys/malloc.h> ! 76: #include <sys/file.h> ! 77: #include <sys/stat.h> ! 78: #include <sys/mount.h> ! 79: #include <sys/namei.h> ! 80: #include <sys/buf.h> ! 81: #include <sys/dirent.h> ! 82: #include <vfs/vfs_support.h> ! 83: #include <miscfs/fdesc/fdesc.h> ! 84: ! 85: #define cttyvp(p) ((p)->p_flag & P_CONTROLT ? (p)->p_session->s_ttyvp : NULL) ! 86: ! 87: #define FDL_WANT 0x01 ! 88: #define FDL_LOCKED 0x02 ! 89: static int fdcache_lock; ! 90: ! 91: dev_t devctty; ! 92: ! 93: #if (FD_STDIN != FD_STDOUT-1) || (FD_STDOUT != FD_STDERR-1) ! 94: FD_STDIN, FD_STDOUT, FD_STDERR must be a sequence n, n+1, n+2 ! 95: #endif ! 96: ! 97: #define NFDCACHE 4 ! 98: ! 99: #define FD_NHASH(ix) \ ! 100: (&fdhashtbl[(ix) & fdhash]) ! 101: LIST_HEAD(fdhashhead, fdescnode) *fdhashtbl; ! 102: u_long fdhash; ! 103: ! 104: /* ! 105: * Initialise cache headers ! 106: */ ! 107: fdesc_init(vfsp) ! 108: struct vfsconf *vfsp; ! 109: { ! 110: ! 111: devctty = makedev(nchrdev, 0); ! 112: fdhashtbl = hashinit(NFDCACHE, M_CACHE, &fdhash); ! 113: } ! 114: ! 115: int ! 116: fdesc_allocvp(ftype, ix, mp, vpp) ! 117: fdntype ftype; ! 118: int ix; ! 119: struct mount *mp; ! 120: struct vnode **vpp; ! 121: { ! 122: struct proc *p = current_proc(); /* XXX */ ! 123: struct fdhashhead *fc; ! 124: struct fdescnode *fd; ! 125: int error = 0; ! 126: ! 127: fc = FD_NHASH(ix); ! 128: loop: ! 129: for (fd = fc->lh_first; fd != 0; fd = fd->fd_hash.le_next) { ! 130: if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { ! 131: if (vget(fd->fd_vnode, 0, p)) ! 132: goto loop; ! 133: *vpp = fd->fd_vnode; ! 134: return (error); ! 135: } ! 136: } ! 137: ! 138: /* ! 139: * otherwise lock the array while we call getnewvnode ! 140: * since that can block. ! 141: */ ! 142: if (fdcache_lock & FDL_LOCKED) { ! 143: fdcache_lock |= FDL_WANT; ! 144: sleep((caddr_t) &fdcache_lock, PINOD); ! 145: goto loop; ! 146: } ! 147: fdcache_lock |= FDL_LOCKED; ! 148: ! 149: MALLOC(fd, void *, sizeof(struct fdescnode), M_TEMP, M_WAITOK); ! 150: error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, vpp); ! 151: if (error) { ! 152: FREE(fd, M_TEMP); ! 153: goto out; ! 154: } ! 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 = VCHR; ! 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: vap->va_uid = 0; ! 430: vap->va_gid = 0; ! 431: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0]; ! 432: vap->va_blocksize = DEV_BSIZE; ! 433: vap->va_atime.tv_sec = boottime.tv_sec; ! 434: vap->va_atime.tv_nsec = 0; ! 435: vap->va_mtime = vap->va_atime; ! 436: vap->va_ctime = vap->va_mtime; ! 437: vap->va_gen = 0; ! 438: vap->va_flags = 0; ! 439: vap->va_rdev = 0; ! 440: vap->va_bytes = 0; ! 441: ! 442: switch (VTOFDESC(vp)->fd_type) { ! 443: case Flink: ! 444: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; ! 445: vap->va_type = VLNK; ! 446: vap->va_nlink = 1; ! 447: vap->va_size = strlen(VTOFDESC(vp)->fd_link); ! 448: break; ! 449: ! 450: case Fctty: ! 451: vap->va_mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; ! 452: vap->va_type = VCHR; ! 453: vap->va_nlink = 1; ! 454: vap->va_size = 0; ! 455: vap->va_rdev = devctty; ! 456: break; ! 457: ! 458: default: ! 459: vap->va_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; ! 460: vap->va_type = VDIR; ! 461: vap->va_nlink = 2; ! 462: vap->va_size = DEV_BSIZE; ! 463: break; ! 464: } ! 465: break; ! 466: ! 467: case Fdesc: ! 468: fd = VTOFDESC(vp)->fd_fd; ! 469: error = fdesc_attr(fd, vap, ap->a_cred, ap->a_p); ! 470: break; ! 471: ! 472: default: ! 473: panic("fdesc_getattr"); ! 474: break; ! 475: } ! 476: ! 477: if (error == 0) ! 478: vp->v_type = vap->va_type; ! 479: ! 480: return (error); ! 481: } ! 482: ! 483: int ! 484: fdesc_setattr(ap) ! 485: struct vop_setattr_args /* { ! 486: struct vnode *a_vp; ! 487: struct vattr *a_vap; ! 488: struct ucred *a_cred; ! 489: struct proc *a_p; ! 490: } */ *ap; ! 491: { ! 492: struct file *fp; ! 493: unsigned fd; ! 494: int error; ! 495: ! 496: /* ! 497: * Can't mess with the root vnode ! 498: */ ! 499: switch (VTOFDESC(ap->a_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(ap->a_vp)->fd_fd; ! 511: if (error = fdgetf(ap->a_p, fd, &fp)) ! 512: return (error); ! 513: ! 514: /* ! 515: * Can setattr the underlying vnode, but not sockets! ! 516: */ ! 517: switch (fp->f_type) { ! 518: case DTYPE_VNODE: ! 519: error = VOP_SETATTR((struct vnode *) fp->f_data, ap->a_vap, ap->a_cred, ap->a_p); ! 520: break; ! 521: ! 522: case DTYPE_SOCKET: ! 523: error = 0; ! 524: break; ! 525: ! 526: default: ! 527: kprintf("fp->f_type = %d\n", fp->f_type); ! 528: error = EBADF; ! 529: break; ! 530: } ! 531: ! 532: return (error); ! 533: } ! 534: ! 535: #define UIO_MX 16 ! 536: ! 537: static struct dirtmp { ! 538: u_long d_fileno; ! 539: u_short d_reclen; ! 540: u_short d_namlen; ! 541: char d_name[8]; ! 542: } rootent[] = { ! 543: { FD_DEVFD, UIO_MX, 2, "fd" }, ! 544: { FD_STDIN, UIO_MX, 5, "stdin" }, ! 545: { FD_STDOUT, UIO_MX, 6, "stdout" }, ! 546: { FD_STDERR, UIO_MX, 6, "stderr" }, ! 547: { FD_CTTY, UIO_MX, 3, "tty" }, ! 548: { 0 } ! 549: }; ! 550: ! 551: int ! 552: fdesc_readdir(ap) ! 553: struct vop_readdir_args /* { ! 554: struct vnode *a_vp; ! 555: struct uio *a_uio; ! 556: struct ucred *a_cred; ! 557: int *a_eofflag; ! 558: u_long *a_cookies; ! 559: int a_ncookies; ! 560: } */ *ap; ! 561: { ! 562: struct uio *uio = ap->a_uio; ! 563: struct proc *p = uio->uio_procp; ! 564: int i, error; ! 565: ! 566: /* ! 567: * We don't allow exporting fdesc mounts, and currently local ! 568: * requests do not need cookies. ! 569: */ ! 570: if (ap->a_ncookies) ! 571: panic("fdesc_readdir: not hungry"); ! 572: ! 573: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 574: case Fctty: ! 575: return (0); ! 576: ! 577: case Fdesc: ! 578: return (ENOTDIR); ! 579: ! 580: default: ! 581: break; ! 582: } ! 583: ! 584: if (VTOFDESC(ap->a_vp)->fd_type == Froot) { ! 585: struct dirent d; ! 586: struct dirent *dp = &d; ! 587: struct dirtmp *dt; ! 588: int fd; ! 589: ! 590: i = uio->uio_offset / UIO_MX; ! 591: error = 0; ! 592: ! 593: while (uio->uio_resid > 0) { ! 594: dt = &rootent[i]; ! 595: if (dt->d_fileno == 0) { ! 596: /**eofflagp = 1;*/ ! 597: break; ! 598: } ! 599: i++; ! 600: ! 601: switch (dt->d_fileno) { ! 602: case FD_CTTY: ! 603: if (cttyvp(uio->uio_procp) == NULL) ! 604: continue; ! 605: break; ! 606: ! 607: case FD_STDIN: ! 608: case FD_STDOUT: ! 609: case FD_STDERR: ! 610: fd = dt->d_fileno - FD_STDIN; ! 611: if (fd >= p->p_fd->fd_nfiles) ! 612: continue; ! 613: if (*fdfile(p, fd) == NULL && ! 614: !(*fdflags(p, fd) & ! 615: UF_RESERVED)) ! 616: continue; ! 617: break; ! 618: } ! 619: bzero((caddr_t) dp, UIO_MX); ! 620: dp->d_fileno = dt->d_fileno; ! 621: dp->d_namlen = dt->d_namlen; ! 622: dp->d_type = DT_UNKNOWN; ! 623: dp->d_reclen = dt->d_reclen; ! 624: bcopy(dt->d_name, dp->d_name, dp->d_namlen+1); ! 625: error = uiomove((caddr_t) dp, UIO_MX, uio); ! 626: if (error) ! 627: break; ! 628: } ! 629: uio->uio_offset = i * UIO_MX; ! 630: return (error); ! 631: } ! 632: ! 633: i = uio->uio_offset / UIO_MX; ! 634: error = 0; ! 635: while (uio->uio_resid > 0) { ! 636: if (i >= p->p_fd->fd_nfiles) ! 637: break; ! 638: ! 639: if (*fdfile(p, i) != NULL && !(*fdflags(p, i) & UF_RESERVED)) { ! 640: struct dirent d; ! 641: struct dirent *dp = &d; ! 642: ! 643: bzero((caddr_t) dp, UIO_MX); ! 644: ! 645: dp->d_namlen = sprintf(dp->d_name, "%d", i); ! 646: dp->d_reclen = UIO_MX; ! 647: dp->d_type = DT_UNKNOWN; ! 648: dp->d_fileno = i + FD_STDIN; ! 649: /* ! 650: * And ship to userland ! 651: */ ! 652: error = uiomove((caddr_t) dp, UIO_MX, uio); ! 653: if (error) ! 654: break; ! 655: } ! 656: i++; ! 657: } ! 658: ! 659: uio->uio_offset = i * UIO_MX; ! 660: return (error); ! 661: } ! 662: ! 663: int ! 664: fdesc_readlink(ap) ! 665: struct vop_readlink_args /* { ! 666: struct vnode *a_vp; ! 667: struct uio *a_uio; ! 668: struct ucred *a_cred; ! 669: } */ *ap; ! 670: { ! 671: struct vnode *vp = ap->a_vp; ! 672: int error; ! 673: ! 674: if (vp->v_type != VLNK) ! 675: return (EPERM); ! 676: ! 677: if (VTOFDESC(vp)->fd_type == Flink) { ! 678: char *ln = VTOFDESC(vp)->fd_link; ! 679: error = uiomove(ln, strlen(ln), ap->a_uio); ! 680: } else { ! 681: error = EOPNOTSUPP; ! 682: } ! 683: ! 684: return (error); ! 685: } ! 686: ! 687: int ! 688: fdesc_read(ap) ! 689: struct vop_read_args /* { ! 690: struct vnode *a_vp; ! 691: struct uio *a_uio; ! 692: int a_ioflag; ! 693: struct ucred *a_cred; ! 694: } */ *ap; ! 695: { ! 696: int error = EOPNOTSUPP; ! 697: ! 698: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 699: case Fctty: ! 700: error = cttyread(devctty, ap->a_uio, ap->a_ioflag); ! 701: break; ! 702: ! 703: default: ! 704: error = EOPNOTSUPP; ! 705: break; ! 706: } ! 707: ! 708: return (error); ! 709: } ! 710: ! 711: int ! 712: fdesc_write(ap) ! 713: struct vop_write_args /* { ! 714: struct vnode *a_vp; ! 715: struct uio *a_uio; ! 716: int a_ioflag; ! 717: struct ucred *a_cred; ! 718: } */ *ap; ! 719: { ! 720: int error = EOPNOTSUPP; ! 721: ! 722: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 723: case Fctty: ! 724: error = cttywrite(devctty, ap->a_uio, ap->a_ioflag); ! 725: break; ! 726: ! 727: default: ! 728: error = EOPNOTSUPP; ! 729: break; ! 730: } ! 731: ! 732: return (error); ! 733: } ! 734: ! 735: int ! 736: fdesc_ioctl(ap) ! 737: struct vop_ioctl_args /* { ! 738: struct vnode *a_vp; ! 739: int a_command; ! 740: caddr_t a_data; ! 741: int a_fflag; ! 742: struct ucred *a_cred; ! 743: struct proc *a_p; ! 744: } */ *ap; ! 745: { ! 746: int error = EOPNOTSUPP; ! 747: ! 748: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 749: case Fctty: ! 750: error = cttyioctl(devctty, ap->a_command, ap->a_data, ! 751: ap->a_fflag, ap->a_p); ! 752: break; ! 753: ! 754: default: ! 755: error = EOPNOTSUPP; ! 756: break; ! 757: } ! 758: ! 759: return (error); ! 760: } ! 761: ! 762: int ! 763: fdesc_select(ap) ! 764: struct vop_select_args /* { ! 765: struct vnode *a_vp; ! 766: int a_which; ! 767: int a_fflags; ! 768: struct ucred *a_cred; ! 769: struct proc *a_p; ! 770: } */ *ap; ! 771: { ! 772: int error = EOPNOTSUPP; ! 773: ! 774: switch (VTOFDESC(ap->a_vp)->fd_type) { ! 775: case Fctty: ! 776: error = cttyselect(devctty, ap->a_fflags, ap->a_p); ! 777: break; ! 778: ! 779: default: ! 780: error = EOPNOTSUPP; ! 781: break; ! 782: } ! 783: ! 784: return (error); ! 785: } ! 786: ! 787: int ! 788: fdesc_inactive(ap) ! 789: struct vop_inactive_args /* { ! 790: struct vnode *a_vp; ! 791: struct proc *a_p; ! 792: } */ *ap; ! 793: { ! 794: struct vnode *vp = ap->a_vp; ! 795: ! 796: /* ! 797: * Clear out the v_type field to avoid ! 798: * nasty things happening in vgone(). ! 799: */ ! 800: VOP_UNLOCK(vp, 0, ap->a_p); ! 801: vp->v_type = VNON; ! 802: return (0); ! 803: } ! 804: ! 805: int ! 806: fdesc_reclaim(ap) ! 807: struct vop_reclaim_args /* { ! 808: struct vnode *a_vp; ! 809: } */ *ap; ! 810: { ! 811: struct vnode *vp = ap->a_vp; ! 812: struct fdescnode *fd = VTOFDESC(vp); ! 813: ! 814: LIST_REMOVE(fd, fd_hash); ! 815: FREE(vp->v_data, M_TEMP); ! 816: vp->v_data = 0; ! 817: ! 818: return (0); ! 819: } ! 820: ! 821: /* ! 822: * Return POSIX pathconf information applicable to special devices. ! 823: */ ! 824: fdesc_pathconf(ap) ! 825: struct vop_pathconf_args /* { ! 826: struct vnode *a_vp; ! 827: int a_name; ! 828: int *a_retval; ! 829: } */ *ap; ! 830: { ! 831: ! 832: switch (ap->a_name) { ! 833: case _PC_LINK_MAX: ! 834: *ap->a_retval = LINK_MAX; ! 835: return (0); ! 836: case _PC_MAX_CANON: ! 837: *ap->a_retval = MAX_CANON; ! 838: return (0); ! 839: case _PC_MAX_INPUT: ! 840: *ap->a_retval = MAX_INPUT; ! 841: return (0); ! 842: case _PC_PIPE_BUF: ! 843: *ap->a_retval = PIPE_BUF; ! 844: return (0); ! 845: case _PC_CHOWN_RESTRICTED: ! 846: *ap->a_retval = 1; ! 847: return (0); ! 848: case _PC_VDISABLE: ! 849: *ap->a_retval = _POSIX_VDISABLE; ! 850: return (0); ! 851: default: ! 852: return (EINVAL); ! 853: } ! 854: /* NOTREACHED */ ! 855: } ! 856: ! 857: /* ! 858: * Print out the contents of a /dev/fd vnode. ! 859: */ ! 860: /* ARGSUSED */ ! 861: int ! 862: fdesc_print(ap) ! 863: struct vop_print_args /* { ! 864: struct vnode *a_vp; ! 865: } */ *ap; ! 866: { ! 867: ! 868: printf("tag VT_NON, fdesc vnode\n"); ! 869: return (0); ! 870: } ! 871: ! 872: /*void*/ ! 873: int ! 874: fdesc_vfree(ap) ! 875: struct vop_vfree_args /* { ! 876: struct vnode *a_pvp; ! 877: ino_t a_ino; ! 878: int a_mode; ! 879: } */ *ap; ! 880: { ! 881: ! 882: return (0); ! 883: } ! 884: ! 885: /* ! 886: * /dev/fd "should never get here" operation ! 887: */ ! 888: int ! 889: fdesc_badop() ! 890: { ! 891: ! 892: panic("fdesc: bad op"); ! 893: /* NOTREACHED */ ! 894: } ! 895: ! 896: /* Pagein */ ! 897: fdesc_pagein(ap) ! 898: struct vop_pagein_args /* { ! 899: struct vnode *a_vp; ! 900: struct uio *a_uio; ! 901: int a_ioflag; ! 902: struct ucred *a_cred; ! 903: } */ *ap; ! 904: { ! 905: /* pass thru to read */ ! 906: return (VOP_READ(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); ! 907: } ! 908: ! 909: /* Pageout */ ! 910: fdesc_pageout(ap) ! 911: struct vop_pageout_args /* { ! 912: struct vnode *a_vp; ! 913: struct uio *a_uio; ! 914: int a_ioflag; ! 915: struct ucred *a_cred; ! 916: } */ *ap; ! 917: { ! 918: /* pass thru to write */ ! 919: return (VOP_WRITE(ap->a_vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); ! 920: } ! 921: ! 922: #define fdesc_create ((int (*) __P((struct vop_create_args *)))eopnotsupp) ! 923: #define fdesc_mknod ((int (*) __P((struct vop_mknod_args *)))eopnotsupp) ! 924: #define fdesc_close ((int (*) __P((struct vop_close_args *)))nullop) ! 925: #define fdesc_access ((int (*) __P((struct vop_access_args *)))nullop) ! 926: #define fdesc_mmap ((int (*) __P((struct vop_mmap_args *)))eopnotsupp) ! 927: #define fdesc_revoke vop_revoke ! 928: #define fdesc_fsync ((int (*) __P((struct vop_fsync_args *)))nullop) ! 929: #define fdesc_seek ((int (*) __P((struct vop_seek_args *)))nullop) ! 930: #define fdesc_remove ((int (*) __P((struct vop_remove_args *)))eopnotsupp) ! 931: #define fdesc_link ((int (*) __P((struct vop_link_args *)))eopnotsupp) ! 932: #define fdesc_rename ((int (*) __P((struct vop_rename_args *)))eopnotsupp) ! 933: #define fdesc_mkdir ((int (*) __P((struct vop_mkdir_args *)))eopnotsupp) ! 934: #define fdesc_rmdir ((int (*) __P((struct vop_rmdir_args *)))eopnotsupp) ! 935: #define fdesc_symlink ((int (*) __P((struct vop_symlink_args *)))eopnotsupp) ! 936: #define fdesc_abortop ((int (*) __P((struct vop_abortop_args *)))nullop) ! 937: #define fdesc_lock ((int (*) __P((struct vop_lock_args *)))vop_nolock) ! 938: #define fdesc_unlock ((int (*) __P((struct vop_unlock_args *)))vop_nounlock) ! 939: #define fdesc_bmap ((int (*) __P((struct vop_bmap_args *)))fdesc_badop) ! 940: #define fdesc_strategy ((int (*) __P((struct vop_strategy_args *)))fdesc_badop) ! 941: #define fdesc_islocked \ ! 942: ((int (*) __P((struct vop_islocked_args *)))vop_noislocked) ! 943: #define fdesc_advlock ((int (*) __P((struct vop_advlock_args *)))eopnotsupp) ! 944: #define fdesc_blkatoff \ ! 945: ((int (*) __P((struct vop_blkatoff_args *)))eopnotsupp) ! 946: #define fdesc_valloc ((int(*) __P(( \ ! 947: struct vnode *pvp, \ ! 948: int mode, \ ! 949: struct ucred *cred, \ ! 950: struct vnode **vpp))) eopnotsupp) ! 951: #define fdesc_truncate \ ! 952: ((int (*) __P((struct vop_truncate_args *)))eopnotsupp) ! 953: #define fdesc_update ((int (*) __P((struct vop_update_args *)))eopnotsupp) ! 954: #define fdesc_bwrite ((int (*) __P((struct vop_bwrite_args *)))eopnotsupp) ! 955: ! 956: int (**fdesc_vnodeop_p)(); ! 957: struct vnodeopv_entry_desc fdesc_vnodeop_entries[] = { ! 958: { &vop_default_desc, vn_default_error }, ! 959: { &vop_lookup_desc, fdesc_lookup }, /* lookup */ ! 960: { &vop_create_desc, fdesc_create }, /* create */ ! 961: { &vop_mknod_desc, fdesc_mknod }, /* mknod */ ! 962: { &vop_open_desc, fdesc_open }, /* open */ ! 963: { &vop_close_desc, fdesc_close }, /* close */ ! 964: { &vop_access_desc, fdesc_access }, /* access */ ! 965: { &vop_getattr_desc, fdesc_getattr }, /* getattr */ ! 966: { &vop_setattr_desc, fdesc_setattr }, /* setattr */ ! 967: { &vop_read_desc, fdesc_read }, /* read */ ! 968: { &vop_write_desc, fdesc_write }, /* write */ ! 969: { &vop_ioctl_desc, fdesc_ioctl }, /* ioctl */ ! 970: { &vop_select_desc, fdesc_select }, /* select */ ! 971: { &vop_revoke_desc, fdesc_revoke }, /* revoke */ ! 972: { &vop_mmap_desc, fdesc_mmap }, /* mmap */ ! 973: { &vop_fsync_desc, fdesc_fsync }, /* fsync */ ! 974: { &vop_seek_desc, fdesc_seek }, /* seek */ ! 975: { &vop_remove_desc, fdesc_remove }, /* remove */ ! 976: { &vop_link_desc, fdesc_link }, /* link */ ! 977: { &vop_rename_desc, fdesc_rename }, /* rename */ ! 978: { &vop_mkdir_desc, fdesc_mkdir }, /* mkdir */ ! 979: { &vop_rmdir_desc, fdesc_rmdir }, /* rmdir */ ! 980: { &vop_symlink_desc, fdesc_symlink }, /* symlink */ ! 981: { &vop_readdir_desc, fdesc_readdir }, /* readdir */ ! 982: { &vop_readlink_desc, fdesc_readlink }, /* readlink */ ! 983: { &vop_abortop_desc, fdesc_abortop }, /* abortop */ ! 984: { &vop_inactive_desc, fdesc_inactive }, /* inactive */ ! 985: { &vop_reclaim_desc, fdesc_reclaim }, /* reclaim */ ! 986: { &vop_lock_desc, fdesc_lock }, /* lock */ ! 987: { &vop_unlock_desc, fdesc_unlock }, /* unlock */ ! 988: { &vop_bmap_desc, fdesc_bmap }, /* bmap */ ! 989: { &vop_strategy_desc, fdesc_strategy }, /* strategy */ ! 990: { &vop_print_desc, fdesc_print }, /* print */ ! 991: { &vop_islocked_desc, fdesc_islocked }, /* islocked */ ! 992: { &vop_pathconf_desc, fdesc_pathconf }, /* pathconf */ ! 993: { &vop_advlock_desc, fdesc_advlock }, /* advlock */ ! 994: { &vop_blkatoff_desc, fdesc_blkatoff }, /* blkatoff */ ! 995: { &vop_valloc_desc, fdesc_valloc }, /* valloc */ ! 996: { &vop_vfree_desc, fdesc_vfree }, /* vfree */ ! 997: { &vop_truncate_desc, fdesc_truncate }, /* truncate */ ! 998: { &vop_update_desc, fdesc_update }, /* update */ ! 999: { &vop_bwrite_desc, fdesc_bwrite }, /* bwrite */ ! 1000: { &vop_bwrite_desc, fdesc_pagein }, /* pagein */ ! 1001: { &vop_bwrite_desc, fdesc_pageout }, /* pageout */ ! 1002: { &vop_copyfile_desc, err_copyfile }, /* Copyfile */ ! 1003: { (struct vnodeop_desc*)NULL, (int(*)())NULL } ! 1004: }; ! 1005: struct vnodeopv_desc fdesc_vnodeop_opv_desc = ! 1006: { &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.