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