|
|
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: /* $NetBSD: procfs_subr.c,v 1.13 1994/06/29 06:34:57 cgd Exp $ */ ! 26: ! 27: /* ! 28: * Copyright (c) 1993 Jan-Simon Pendry ! 29: * Copyright (c) 1993 ! 30: * The Regents of the University of California. All rights reserved. ! 31: * ! 32: * This code is derived from software contributed to Berkeley by ! 33: * Jan-Simon Pendry. ! 34: * ! 35: * Redistribution and use in source and binary forms, with or without ! 36: * modification, are permitted provided that the following conditions ! 37: * are met: ! 38: * 1. Redistributions of source code must retain the above copyright ! 39: * notice, this list of conditions and the following disclaimer. ! 40: * 2. Redistributions in binary form must reproduce the above copyright ! 41: * notice, this list of conditions and the following disclaimer in the ! 42: * documentation and/or other materials provided with the distribution. ! 43: * 3. All advertising materials mentioning features or use of this software ! 44: * must display the following acknowledgement: ! 45: * This product includes software developed by the University of ! 46: * California, Berkeley and its contributors. ! 47: * 4. Neither the name of the University nor the names of its contributors ! 48: * may be used to endorse or promote products derived from this software ! 49: * without specific prior written permission. ! 50: * ! 51: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 52: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 53: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 54: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 55: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 56: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 57: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 58: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 59: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 60: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 61: * SUCH DAMAGE. ! 62: * ! 63: * @(#)procfs_subr.c 8.5 (Berkeley) 6/15/94 ! 64: */ ! 65: ! 66: #include <sys/param.h> ! 67: #include <sys/systm.h> ! 68: #include <sys/time.h> ! 69: #include <sys/kernel.h> ! 70: #include <sys/proc.h> ! 71: #include <sys/vnode.h> ! 72: #include <sys/malloc.h> ! 73: #include <miscfs/procfs/procfs.h> ! 74: ! 75: static struct pfsnode *pfshead; ! 76: static int pfsvplock; ! 77: ! 78: /* ! 79: * allocate a pfsnode/vnode pair. the vnode is ! 80: * referenced, but not locked. ! 81: * ! 82: * the pid, pfs_type, and mount point uniquely ! 83: * identify a pfsnode. the mount point is needed ! 84: * because someone might mount this filesystem ! 85: * twice. ! 86: * ! 87: * all pfsnodes are maintained on a singly-linked ! 88: * list. new nodes are only allocated when they cannot ! 89: * be found on this list. entries on the list are ! 90: * removed when the vfs reclaim entry is called. ! 91: * ! 92: * a single lock is kept for the entire list. this is ! 93: * needed because the getnewvnode() function can block ! 94: * waiting for a vnode to become free, in which case there ! 95: * may be more than one process trying to get the same ! 96: * vnode. this lock is only taken if we are going to ! 97: * call getnewvnode, since the kernel itself is single-threaded. ! 98: * ! 99: * if an entry is found on the list, then call vget() to ! 100: * take a reference. this is done because there may be ! 101: * zero references to it and so it needs to removed from ! 102: * the vnode free list. ! 103: */ ! 104: int ! 105: procfs_allocvp(mp, vpp, pid, pfs_type) ! 106: struct mount *mp; ! 107: struct vnode **vpp; ! 108: long pid; ! 109: pfstype pfs_type; ! 110: { ! 111: struct pfsnode *pfs; ! 112: struct vnode *vp; ! 113: struct pfsnode **pp; ! 114: int error; ! 115: ! 116: loop: ! 117: for (pfs = pfshead; pfs != 0; pfs = pfs->pfs_next) { ! 118: vp = PFSTOV(pfs); ! 119: if (pfs->pfs_pid == pid && ! 120: pfs->pfs_type == pfs_type && ! 121: vp->v_mount == mp) { ! 122: if (vget(vp, 0)) ! 123: goto loop; ! 124: *vpp = vp; ! 125: return (0); ! 126: } ! 127: } ! 128: ! 129: /* ! 130: * otherwise lock the vp list while we call getnewvnode ! 131: * since that can block. ! 132: */ ! 133: if (pfsvplock & PROCFS_LOCKED) { ! 134: pfsvplock |= PROCFS_WANT; ! 135: sleep((caddr_t) &pfsvplock, PINOD); ! 136: goto loop; ! 137: } ! 138: pfsvplock |= PROCFS_LOCKED; ! 139: ! 140: if (error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, vpp)) ! 141: goto out; ! 142: vp = *vpp; ! 143: ! 144: MALLOC(pfs, void *, sizeof(struct pfsnode), M_TEMP, M_WAITOK); ! 145: vp->v_data = pfs; ! 146: ! 147: pfs->pfs_next = 0; ! 148: pfs->pfs_pid = (pid_t) pid; ! 149: pfs->pfs_type = pfs_type; ! 150: pfs->pfs_vnode = vp; ! 151: pfs->pfs_flags = 0; ! 152: pfs->pfs_fileno = PROCFS_FILENO(pid, pfs_type); ! 153: ! 154: switch (pfs_type) { ! 155: case Proot: /* /proc = dr-xr-xr-x */ ! 156: pfs->pfs_mode = (VREAD|VEXEC) | ! 157: (VREAD|VEXEC) >> 3 | ! 158: (VREAD|VEXEC) >> 6; ! 159: vp->v_type = VDIR; ! 160: vp->v_flag = VROOT; ! 161: break; ! 162: ! 163: case Pcurproc: /* /proc/curproc = lr--r--r-- */ ! 164: pfs->pfs_mode = (VREAD) | ! 165: (VREAD >> 3) | ! 166: (VREAD >> 6); ! 167: vp->v_type = VLNK; ! 168: break; ! 169: ! 170: case Pproc: ! 171: pfs->pfs_mode = (VREAD|VEXEC) | ! 172: (VREAD|VEXEC) >> 3 | ! 173: (VREAD|VEXEC) >> 6; ! 174: vp->v_type = VDIR; ! 175: break; ! 176: ! 177: case Pfile: ! 178: case Pmem: ! 179: case Pregs: ! 180: case Pfpregs: ! 181: pfs->pfs_mode = (VREAD|VWRITE); ! 182: vp->v_type = VREG; ! 183: break; ! 184: ! 185: case Pctl: ! 186: case Pnote: ! 187: case Pnotepg: ! 188: pfs->pfs_mode = (VWRITE); ! 189: vp->v_type = VREG; ! 190: break; ! 191: ! 192: case Pstatus: ! 193: pfs->pfs_mode = (VREAD) | ! 194: (VREAD >> 3) | ! 195: (VREAD >> 6); ! 196: vp->v_type = VREG; ! 197: break; ! 198: ! 199: default: ! 200: panic("procfs_allocvp"); ! 201: } ! 202: ! 203: /* add to procfs vnode list */ ! 204: for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next) ! 205: continue; ! 206: *pp = pfs; ! 207: ! 208: out: ! 209: pfsvplock &= ~PROCFS_LOCKED; ! 210: ! 211: if (pfsvplock & PROCFS_WANT) { ! 212: pfsvplock &= ~PROCFS_WANT; ! 213: wakeup((caddr_t) &pfsvplock); ! 214: } ! 215: ! 216: return (error); ! 217: } ! 218: ! 219: int ! 220: procfs_freevp(vp) ! 221: struct vnode *vp; ! 222: { ! 223: struct pfsnode **pfspp; ! 224: struct pfsnode *pfs = VTOPFS(vp); ! 225: ! 226: for (pfspp = &pfshead; *pfspp != 0; pfspp = &(*pfspp)->pfs_next) { ! 227: if (*pfspp == pfs) { ! 228: *pfspp = pfs->pfs_next; ! 229: break; ! 230: } ! 231: } ! 232: ! 233: FREE(vp->v_data, M_TEMP); ! 234: vp->v_data = 0; ! 235: return (0); ! 236: } ! 237: ! 238: int ! 239: procfs_rw(ap) ! 240: struct vop_read_args *ap; ! 241: { ! 242: struct vnode *vp = ap->a_vp; ! 243: struct uio *uio = ap->a_uio; ! 244: struct proc *curp = uio->uio_procp; ! 245: struct pfsnode *pfs = VTOPFS(vp); ! 246: struct proc *p; ! 247: ! 248: p = PFIND(pfs->pfs_pid); ! 249: if (p == 0) ! 250: return (EINVAL); ! 251: ! 252: switch (pfs->pfs_type) { ! 253: case Pnote: ! 254: case Pnotepg: ! 255: return (procfs_donote(curp, p, pfs, uio)); ! 256: ! 257: case Pregs: ! 258: return (procfs_doregs(curp, p, pfs, uio)); ! 259: ! 260: case Pfpregs: ! 261: return (procfs_dofpregs(curp, p, pfs, uio)); ! 262: ! 263: case Pctl: ! 264: return (procfs_doctl(curp, p, pfs, uio)); ! 265: ! 266: case Pstatus: ! 267: return (procfs_dostatus(curp, p, pfs, uio)); ! 268: ! 269: case Pmem: ! 270: return (procfs_domem(curp, p, pfs, uio)); ! 271: ! 272: default: ! 273: return (EOPNOTSUPP); ! 274: } ! 275: } ! 276: ! 277: /* ! 278: * Get a string from userland into (buf). Strip a trailing ! 279: * nl character (to allow easy access from the shell). ! 280: * The buffer should be *buflenp + 1 chars long. vfs_getuserstr ! 281: * will automatically add a nul char at the end. ! 282: * ! 283: * Returns 0 on success or the following errors ! 284: * ! 285: * EINVAL: file offset is non-zero. ! 286: * EMSGSIZE: message is longer than kernel buffer ! 287: * EFAULT: user i/o buffer is not addressable ! 288: */ ! 289: int ! 290: vfs_getuserstr(uio, buf, buflenp) ! 291: struct uio *uio; ! 292: char *buf; ! 293: int *buflenp; ! 294: { ! 295: int xlen; ! 296: int error; ! 297: ! 298: if (uio->uio_offset != 0) ! 299: return (EINVAL); ! 300: ! 301: xlen = *buflenp; ! 302: ! 303: /* must be able to read the whole string in one go */ ! 304: if (xlen < uio->uio_resid) ! 305: return (EMSGSIZE); ! 306: xlen = uio->uio_resid; ! 307: ! 308: if (error = uiomove(buf, xlen, uio)) ! 309: return (error); ! 310: ! 311: /* allow multiple writes without seeks */ ! 312: uio->uio_offset = 0; ! 313: ! 314: /* cleanup string and remove trailing newline */ ! 315: buf[xlen] = '\0'; ! 316: xlen = strlen(buf); ! 317: if (xlen > 0 && buf[xlen-1] == '\n') ! 318: buf[--xlen] = '\0'; ! 319: *buflenp = xlen; ! 320: ! 321: return (0); ! 322: } ! 323: ! 324: vfs_namemap_t * ! 325: vfs_findname(nm, buf, buflen) ! 326: vfs_namemap_t *nm; ! 327: char *buf; ! 328: int buflen; ! 329: { ! 330: ! 331: for (; nm->nm_name; nm++) ! 332: if (bcmp(buf, (char *) nm->nm_name, buflen+1) == 0) ! 333: return (nm); ! 334: ! 335: return (0); ! 336: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.