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