]>
git.saurik.com Git - apple/xnu.git/blob - bsd/miscfs/procfs/procfs_subr.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
22 /* $NetBSD: procfs_subr.c,v 1.13 1994/06/29 06:34:57 cgd Exp $ */
25 * Copyright (c) 1993 Jan-Simon Pendry
27 * The Regents of the University of California. All rights reserved.
29 * This code is derived from software contributed to Berkeley by
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
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.
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
60 * @(#)procfs_subr.c 8.5 (Berkeley) 6/15/94
63 #include <sys/param.h>
64 #include <sys/systm.h>
66 #include <sys/kernel.h>
68 #include <sys/vnode.h>
69 #include <sys/malloc.h>
71 #include <miscfs/procfs/procfs.h>
73 static struct pfsnode
*pfshead
;
77 * allocate a pfsnode/vnode pair. the vnode is
78 * referenced, but not locked.
80 * the pid, pfs_type, and mount point uniquely
81 * identify a pfsnode. the mount point is needed
82 * because someone might mount this filesystem
85 * all pfsnodes are maintained on a singly-linked
86 * list. new nodes are only allocated when they cannot
87 * be found on this list. entries on the list are
88 * removed when the vfs reclaim entry is called.
90 * a single lock is kept for the entire list. this is
91 * needed because the getnewvnode() function can block
92 * waiting for a vnode to become free, in which case there
93 * may be more than one process trying to get the same
94 * vnode. this lock is only taken if we are going to
95 * call getnewvnode, since the kernel itself is single-threaded.
97 * if an entry is found on the list, then call vget() to
98 * take a reference. this is done because there may be
99 * zero references to it and so it needs to removed from
100 * the vnode free list.
103 procfs_allocvp(mp
, vpp
, pid
, pfs_type
)
115 for (pfs
= pfshead
; pfs
!= 0; pfs
= pfs
->pfs_next
) {
117 if (pfs
->pfs_pid
== pid
&&
118 pfs
->pfs_type
== pfs_type
&&
120 if (vget(vp
, 0, current_proc()))
128 * otherwise lock the vp list while we call getnewvnode
129 * since that can block.
131 if (pfsvplock
& PROCFS_LOCKED
) {
132 pfsvplock
|= PROCFS_WANT
;
133 sleep((caddr_t
) &pfsvplock
, PINOD
);
136 pfsvplock
|= PROCFS_LOCKED
;
138 MALLOC(pfs
, void *, sizeof(struct pfsnode
), M_TEMP
, M_WAITOK
);
139 if (error
= getnewvnode(VT_PROCFS
, mp
, procfs_vnodeop_p
, vpp
)) {
147 pfs
->pfs_pid
= (pid_t
) pid
;
148 pfs
->pfs_type
= pfs_type
;
151 pfs
->pfs_fileno
= PROCFS_FILENO(pid
, pfs_type
);
154 case Proot
: /* /proc = dr-xr-xr-x */
155 pfs
->pfs_mode
= (VREAD
|VEXEC
) |
162 case Pcurproc
: /* /proc/curproc = lr--r--r-- */
163 pfs
->pfs_mode
= (VREAD
) |
170 pfs
->pfs_mode
= (VREAD
|VEXEC
) |
180 pfs
->pfs_mode
= (VREAD
|VWRITE
);
187 pfs
->pfs_mode
= (VWRITE
);
192 pfs
->pfs_mode
= (VREAD
) |
199 panic("procfs_allocvp");
202 if (vp
->v_type
== VREG
)
205 /* add to procfs vnode list */
206 for (pp
= &pfshead
; *pp
; pp
= &(*pp
)->pfs_next
)
211 pfsvplock
&= ~PROCFS_LOCKED
;
213 if (pfsvplock
& PROCFS_WANT
) {
214 pfsvplock
&= ~PROCFS_WANT
;
215 wakeup((caddr_t
) &pfsvplock
);
225 struct pfsnode
**pfspp
;
226 struct pfsnode
*pfs
= VTOPFS(vp
);
228 for (pfspp
= &pfshead
; *pfspp
!= 0; pfspp
= &(*pfspp
)->pfs_next
) {
230 *pfspp
= pfs
->pfs_next
;
235 FREE(vp
->v_data
, M_TEMP
);
242 struct vop_read_args
*ap
;
244 struct vnode
*vp
= ap
->a_vp
;
245 struct uio
*uio
= ap
->a_uio
;
246 struct proc
*curp
= uio
->uio_procp
;
247 struct pfsnode
*pfs
= VTOPFS(vp
);
250 p
= PFIND(pfs
->pfs_pid
);
254 switch (pfs
->pfs_type
) {
257 return (procfs_donote(curp
, p
, pfs
, uio
));
260 return (procfs_doregs(curp
, p
, pfs
, uio
));
263 return (procfs_dofpregs(curp
, p
, pfs
, uio
));
266 return (procfs_doctl(curp
, p
, pfs
, uio
));
269 return (procfs_dostatus(curp
, p
, pfs
, uio
));
272 return (procfs_domem(curp
, p
, pfs
, uio
));
280 * Get a string from userland into (buf). Strip a trailing
281 * nl character (to allow easy access from the shell).
282 * The buffer should be *buflenp + 1 chars long. vfs_getuserstr
283 * will automatically add a nul char at the end.
285 * Returns 0 on success or the following errors
287 * EINVAL: file offset is non-zero.
288 * EMSGSIZE: message is longer than kernel buffer
289 * EFAULT: user i/o buffer is not addressable
292 vfs_getuserstr(uio
, buf
, buflenp
)
300 if (uio
->uio_offset
!= 0)
305 /* must be able to read the whole string in one go */
306 if (xlen
< uio
->uio_resid
)
308 xlen
= uio
->uio_resid
;
310 if (error
= uiomove(buf
, xlen
, uio
))
313 /* allow multiple writes without seeks */
316 /* cleanup string and remove trailing newline */
319 if (xlen
> 0 && buf
[xlen
-1] == '\n')
327 vfs_findname(nm
, buf
, buflen
)
333 for (; nm
->nm_name
; nm
++)
334 if (bcmp(buf
, (char *) nm
->nm_name
, buflen
+1) == 0)