|
|
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.