procfs_vnops.c revision 1.20 1 1.1 pk /*
2 1.9 cgd * Copyright (c) 1993 The Regents of the University of California.
3 1.9 cgd * Copyright (c) 1993 Jan-Simon Pendry
4 1.2 pk * All rights reserved.
5 1.2 pk *
6 1.9 cgd * This code is derived from software contributed to Berkeley by
7 1.9 cgd * Jan-Simon Pendry.
8 1.9 cgd *
9 1.2 pk * Redistribution and use in source and binary forms, with or without
10 1.2 pk * modification, are permitted provided that the following conditions
11 1.2 pk * are met:
12 1.2 pk * 1. Redistributions of source code must retain the above copyright
13 1.2 pk * notice, this list of conditions and the following disclaimer.
14 1.2 pk * 2. Redistributions in binary form must reproduce the above copyright
15 1.2 pk * notice, this list of conditions and the following disclaimer in the
16 1.2 pk * documentation and/or other materials provided with the distribution.
17 1.2 pk * 3. All advertising materials mentioning features or use of this software
18 1.2 pk * must display the following acknowledgement:
19 1.9 cgd * This product includes software developed by the University of
20 1.9 cgd * California, Berkeley and its contributors.
21 1.9 cgd * 4. Neither the name of the University nor the names of its contributors
22 1.9 cgd * may be used to endorse or promote products derived from this software
23 1.9 cgd * without specific prior written permission.
24 1.9 cgd *
25 1.9 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 1.9 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 1.9 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 1.9 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 1.9 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 1.9 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 1.9 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 1.9 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 1.9 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 1.9 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 1.9 cgd * SUCH DAMAGE.
36 1.2 pk *
37 1.9 cgd * From:
38 1.9 cgd * Id: procfs_vnops.c,v 4.2 1994/01/02 15:28:44 jsp Exp
39 1.9 cgd *
40 1.20 cgd * $Id: procfs_vnops.c,v 1.20 1994/05/05 05:39:17 cgd Exp $
41 1.2 pk */
42 1.2 pk
43 1.2 pk /*
44 1.9 cgd * procfs vnode interface
45 1.1 pk */
46 1.1 pk
47 1.8 mycroft #include <sys/param.h>
48 1.8 mycroft #include <sys/systm.h>
49 1.8 mycroft #include <sys/time.h>
50 1.8 mycroft #include <sys/kernel.h>
51 1.8 mycroft #include <sys/file.h>
52 1.8 mycroft #include <sys/proc.h>
53 1.8 mycroft #include <sys/vnode.h>
54 1.8 mycroft #include <sys/namei.h>
55 1.9 cgd #include <sys/malloc.h>
56 1.8 mycroft #include <sys/resourcevar.h>
57 1.14 cgd #include <sys/ptrace.h>
58 1.9 cgd #include <miscfs/procfs/procfs.h>
59 1.19 cgd #include <vm/vm.h>
60 1.1 pk
61 1.11 cgd #include <machine/reg.h>
62 1.11 cgd
63 1.9 cgd /*
64 1.9 cgd * Vnode Operations.
65 1.9 cgd *
66 1.9 cgd */
67 1.1 pk
68 1.1 pk /*
69 1.9 cgd * This is a list of the valid names in the
70 1.9 cgd * process-specific sub-directories. It is
71 1.9 cgd * used in procfs_lookup and procfs_readdir
72 1.9 cgd */
73 1.9 cgd static struct pfsnames {
74 1.9 cgd u_short d_namlen;
75 1.9 cgd char d_name[PROCFS_NAMELEN];
76 1.9 cgd pfstype d_pfstype;
77 1.18 cgd int (*d_valid) __P((struct proc *procp));
78 1.9 cgd } procent[] = {
79 1.9 cgd #define N(s) sizeof(s)-1, s
80 1.9 cgd /* namlen, nam, type */
81 1.18 cgd { N("."), Pproc, NULL },
82 1.18 cgd { N(".."), Proot, NULL },
83 1.18 cgd { N("file"), Pfile, procfs_validfile },
84 1.18 cgd { N("mem"), Pmem, NULL },
85 1.18 cgd { N("regs"), Pregs, procfs_validregs },
86 1.18 cgd { N("fpregs"), Pfpregs, procfs_validfpregs },
87 1.18 cgd { N("ctl"), Pctl, NULL },
88 1.18 cgd { N("status"), Pstatus, NULL },
89 1.18 cgd { N("note"), Pnote, NULL },
90 1.18 cgd { N("notepg"), Pnotepg, NULL },
91 1.9 cgd #undef N
92 1.1 pk };
93 1.9 cgd #define Nprocent (sizeof(procent)/sizeof(procent[0]))
94 1.9 cgd
95 1.12 ws #define PROCFS_XFILES 3 /* number of other entries, like "curproc" */
96 1.12 ws
97 1.9 cgd static pid_t atopid __P((const char *, u_int));
98 1.1 pk
99 1.1 pk /*
100 1.9 cgd * set things up for doing i/o on
101 1.9 cgd * the pfsnode (vp). (vp) is locked
102 1.9 cgd * on entry, and should be left locked
103 1.9 cgd * on exit.
104 1.1 pk *
105 1.9 cgd * for procfs we don't need to do anything
106 1.9 cgd * in particular for i/o. all that is done
107 1.9 cgd * is to support exclusive open on process
108 1.9 cgd * memory images.
109 1.1 pk */
110 1.9 cgd procfs_open(vp, mode, cred, p)
111 1.9 cgd struct vnode *vp;
112 1.1 pk int mode;
113 1.1 pk struct ucred *cred;
114 1.1 pk struct proc *p;
115 1.1 pk {
116 1.9 cgd struct pfsnode *pfs = VTOPFS(vp);
117 1.9 cgd
118 1.9 cgd switch (pfs->pfs_type) {
119 1.9 cgd case Pmem:
120 1.9 cgd if (PFIND(pfs->pfs_pid) == 0)
121 1.9 cgd return (ENOENT); /* was ESRCH, jsp */
122 1.9 cgd
123 1.9 cgd if ((pfs->pfs_flags & FWRITE) && (mode & O_EXCL) ||
124 1.9 cgd (pfs->pfs_flags & O_EXCL) && (mode & FWRITE))
125 1.9 cgd return (EBUSY);
126 1.1 pk
127 1.1 pk
128 1.9 cgd if (mode & FWRITE)
129 1.9 cgd pfs->pfs_flags = (mode & (FWRITE|O_EXCL));
130 1.1 pk
131 1.9 cgd return (0);
132 1.1 pk
133 1.9 cgd default:
134 1.9 cgd break;
135 1.9 cgd }
136 1.1 pk
137 1.9 cgd return (0);
138 1.1 pk }
139 1.1 pk
140 1.1 pk /*
141 1.9 cgd * close the pfsnode (vp) after doing i/o.
142 1.9 cgd * (vp) is not locked on entry or exit.
143 1.9 cgd *
144 1.9 cgd * nothing to do for procfs other than undo
145 1.9 cgd * any exclusive open flag (see _open above).
146 1.1 pk */
147 1.9 cgd procfs_close(vp, flag, cred, p)
148 1.9 cgd struct vnode *vp;
149 1.1 pk int flag;
150 1.1 pk struct ucred *cred;
151 1.1 pk struct proc *p;
152 1.1 pk {
153 1.9 cgd struct pfsnode *pfs = VTOPFS(vp);
154 1.1 pk
155 1.9 cgd switch (pfs->pfs_type) {
156 1.9 cgd case Pmem:
157 1.9 cgd if ((flag & FWRITE) && (pfs->pfs_flags & O_EXCL))
158 1.9 cgd pfs->pfs_flags &= ~(FWRITE|O_EXCL);
159 1.9 cgd break;
160 1.9 cgd }
161 1.1 pk
162 1.1 pk return (0);
163 1.1 pk }
164 1.1 pk
165 1.1 pk /*
166 1.9 cgd * do an ioctl operation on pfsnode (vp).
167 1.9 cgd * (vp) is not locked on entry or exit.
168 1.1 pk */
169 1.9 cgd procfs_ioctl(vp, com, data, fflag, cred, p)
170 1.1 pk struct vnode *vp;
171 1.1 pk int com;
172 1.1 pk caddr_t data;
173 1.1 pk int fflag;
174 1.1 pk struct ucred *cred;
175 1.1 pk struct proc *p;
176 1.1 pk {
177 1.1 pk
178 1.9 cgd return (ENOTTY);
179 1.1 pk }
180 1.1 pk
181 1.1 pk /*
182 1.9 cgd * do block mapping for pfsnode (vp).
183 1.9 cgd * since we don't use the buffer cache
184 1.9 cgd * for procfs this function should never
185 1.9 cgd * be called. in any case, it's not clear
186 1.9 cgd * what part of the kernel ever makes use
187 1.9 cgd * of this function. for sanity, this is the
188 1.9 cgd * usual no-op bmap, although returning
189 1.9 cgd * (EIO) would be a reasonable alternative.
190 1.1 pk */
191 1.9 cgd procfs_bmap(vp, bn, vpp, bnp)
192 1.1 pk struct vnode *vp;
193 1.1 pk daddr_t bn;
194 1.1 pk struct vnode **vpp;
195 1.1 pk daddr_t *bnp;
196 1.1 pk {
197 1.1 pk
198 1.1 pk if (vpp != NULL)
199 1.1 pk *vpp = vp;
200 1.1 pk if (bnp != NULL)
201 1.1 pk *bnp = bn;
202 1.1 pk return (0);
203 1.1 pk }
204 1.1 pk
205 1.1 pk /*
206 1.9 cgd * _inactive is called when the pfsnode
207 1.9 cgd * is vrele'd and the reference count goes
208 1.9 cgd * to zero. (vp) will be on the vnode free
209 1.9 cgd * list, so to get it back vget() must be
210 1.9 cgd * used.
211 1.9 cgd *
212 1.9 cgd * for procfs, check if the process is still
213 1.9 cgd * alive and if it isn't then just throw away
214 1.9 cgd * the vnode by calling vgone(). this may
215 1.9 cgd * be overkill and a waste of time since the
216 1.9 cgd * chances are that the process will still be
217 1.9 cgd * there and PFIND is not free.
218 1.9 cgd *
219 1.9 cgd * (vp) is not locked on entry or exit.
220 1.1 pk */
221 1.9 cgd procfs_inactive(vp, p)
222 1.1 pk struct vnode *vp;
223 1.1 pk struct proc *p;
224 1.1 pk {
225 1.9 cgd struct pfsnode *pfs = VTOPFS(vp);
226 1.1 pk
227 1.9 cgd if (PFIND(pfs->pfs_pid) == 0)
228 1.1 pk vgone(vp);
229 1.5 pk
230 1.9 cgd return (0);
231 1.1 pk }
232 1.1 pk
233 1.1 pk /*
234 1.9 cgd * _reclaim is called when getnewvnode()
235 1.9 cgd * wants to make use of an entry on the vnode
236 1.9 cgd * free list. at this time the filesystem needs
237 1.9 cgd * to free any private data and remove the node
238 1.9 cgd * from any private lists.
239 1.1 pk */
240 1.9 cgd procfs_reclaim(vp)
241 1.1 pk struct vnode *vp;
242 1.1 pk {
243 1.9 cgd int error;
244 1.1 pk
245 1.9 cgd error = procfs_freevp(vp);
246 1.9 cgd return (error);
247 1.1 pk }
248 1.1 pk
249 1.1 pk /*
250 1.9 cgd * _print is used for debugging.
251 1.9 cgd * just print a readable description
252 1.9 cgd * of (vp).
253 1.1 pk */
254 1.9 cgd procfs_print(vp)
255 1.1 pk struct vnode *vp;
256 1.1 pk {
257 1.9 cgd struct pfsnode *pfs = VTOPFS(vp);
258 1.5 pk
259 1.9 cgd printf("tag VT_PROCFS, pid %d, mode %x, flags %x\n",
260 1.9 cgd pfs->pfs_pid,
261 1.9 cgd pfs->pfs_mode, pfs->pfs_flags);
262 1.1 pk }
263 1.1 pk
264 1.1 pk /*
265 1.9 cgd * _abortop is called when operations such as
266 1.9 cgd * rename and create fail. this entry is responsible
267 1.9 cgd * for undoing any side-effects caused by the lookup.
268 1.9 cgd * this will always include freeing the pathname buffer.
269 1.1 pk */
270 1.9 cgd procfs_abortop(ndp)
271 1.9 cgd struct nameidata *ndp;
272 1.1 pk {
273 1.9 cgd
274 1.9 cgd if ((ndp->ni_nameiop & (HASBUF | SAVESTART)) == HASBUF)
275 1.9 cgd FREE(ndp->ni_pnbuf, M_NAMEI);
276 1.9 cgd return (0);
277 1.1 pk }
278 1.1 pk
279 1.1 pk /*
280 1.9 cgd * generic entry point for unsupported operations
281 1.1 pk */
282 1.9 cgd procfs_badop()
283 1.1 pk {
284 1.1 pk
285 1.9 cgd return (EIO);
286 1.1 pk }
287 1.1 pk
288 1.1 pk /*
289 1.9 cgd * Invent attributes for pfsnode (vp) and store
290 1.9 cgd * them in (vap).
291 1.9 cgd * Directories lengths are returned as zero since
292 1.9 cgd * any real length would require the genuine size
293 1.9 cgd * to be computed, and nothing cares anyway.
294 1.9 cgd *
295 1.9 cgd * this is relatively minimal for procfs.
296 1.1 pk */
297 1.9 cgd procfs_getattr(vp, vap, cred, p)
298 1.1 pk struct vnode *vp;
299 1.1 pk struct vattr *vap;
300 1.1 pk struct ucred *cred;
301 1.1 pk struct proc *p;
302 1.1 pk {
303 1.9 cgd struct pfsnode *pfs = VTOPFS(vp);
304 1.1 pk struct proc *procp;
305 1.9 cgd int error;
306 1.1 pk
307 1.9 cgd /* start by zeroing out the attributes */
308 1.1 pk VATTR_NULL(vap);
309 1.9 cgd
310 1.9 cgd /* next do all the common fields */
311 1.1 pk vap->va_type = vp->v_type;
312 1.9 cgd vap->va_mode = pfs->pfs_mode;
313 1.9 cgd vap->va_fileid = pfs->pfs_fileno;
314 1.9 cgd vap->va_flags = 0;
315 1.19 cgd vap->va_blocksize = PAGE_SIZE;
316 1.9 cgd vap->va_bytes = vap->va_size = 0;
317 1.9 cgd
318 1.9 cgd /*
319 1.9 cgd * Make all times be current TOD.
320 1.9 cgd * It would be possible to get the process start
321 1.9 cgd * time from the p_stat structure, but there's
322 1.9 cgd * no "file creation" time stamp anyway, and the
323 1.9 cgd * p_stat structure is not addressible if u. gets
324 1.9 cgd * swapped out for that process.
325 1.9 cgd */
326 1.9 cgd microtime(&vap->va_ctime);
327 1.9 cgd vap->va_atime = vap->va_mtime = vap->va_ctime;
328 1.9 cgd
329 1.12 ws error = 0;
330 1.12 ws
331 1.12 ws if (pfs->pfs_type != Proot) {
332 1.12 ws /* check the process still exists */
333 1.12 ws procp = PFIND(pfs->pfs_pid);
334 1.12 ws if (procp == 0)
335 1.12 ws return (ENOENT);
336 1.12 ws /* most of the time we want these values */
337 1.12 ws vap->va_nlink = 1;
338 1.12 ws vap->va_uid = procp->p_ucred->cr_uid;
339 1.12 ws vap->va_gid = procp->p_ucred->cr_gid;
340 1.12 ws }
341 1.12 ws
342 1.9 cgd /*
343 1.9 cgd * now do the object specific fields
344 1.9 cgd *
345 1.9 cgd * The size could be set from struct reg, but it's hardly
346 1.9 cgd * worth the trouble, and it puts some (potentially) machine
347 1.9 cgd * dependent data into this machine-independent code. If it
348 1.9 cgd * becomes important then this function should break out into
349 1.9 cgd * a per-file stat function in the corresponding .c file.
350 1.9 cgd */
351 1.1 pk
352 1.9 cgd switch (pfs->pfs_type) {
353 1.9 cgd case Proot:
354 1.12 ws switch ((int)pfs->pfs_pid) {
355 1.12 ws case 0: /* /proc */
356 1.12 ws vap->va_nlink = 2;
357 1.12 ws vap->va_uid = 0;
358 1.12 ws vap->va_gid = 0;
359 1.12 ws vap->va_bytes = vap->va_size
360 1.12 ws = (maxproc + 1 + PROCFS_XFILES) * UIO_MX;
361 1.12 ws break;
362 1.12 ws case 1: /* /proc/curproc */
363 1.12 ws vap->va_nlink = 1;
364 1.12 ws vap->va_uid = 0;
365 1.12 ws vap->va_gid = 0;
366 1.12 ws break;
367 1.12 ws default:
368 1.12 ws panic("procfs_getattr root");
369 1.12 ws }
370 1.9 cgd break;
371 1.9 cgd
372 1.9 cgd case Pproc:
373 1.9 cgd vap->va_nlink = 2;
374 1.12 ws vap->va_bytes = vap->va_size = Nprocent * UIO_MX;
375 1.9 cgd break;
376 1.9 cgd
377 1.9 cgd case Pmem:
378 1.9 cgd vap->va_bytes = vap->va_size =
379 1.9 cgd ctob(procp->p_vmspace->vm_tsize +
380 1.9 cgd procp->p_vmspace->vm_dsize +
381 1.9 cgd procp->p_vmspace->vm_ssize);
382 1.9 cgd break;
383 1.9 cgd
384 1.18 cgd #if defined(PT_GETREGS) || defined(PT_SETREGS)
385 1.9 cgd case Pregs:
386 1.11 cgd vap->va_bytes = vap->va_size = sizeof(struct reg);
387 1.18 cgd break;
388 1.14 cgd #endif
389 1.14 cgd
390 1.18 cgd #if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
391 1.14 cgd case Pfpregs:
392 1.14 cgd vap->va_bytes = vap->va_size = sizeof(struct fpreg);
393 1.18 cgd break;
394 1.14 cgd #endif
395 1.12 ws
396 1.12 ws case Pstatus:
397 1.12 ws vap->va_bytes = vap->va_size = 256; /* only a maximum */
398 1.12 ws break;
399 1.12 ws
400 1.9 cgd case Pctl:
401 1.13 ws vap->va_bytes = vap->va_size = PROCFS_CTLLEN;
402 1.12 ws break;
403 1.12 ws
404 1.9 cgd case Pnote:
405 1.13 ws vap->va_bytes = vap->va_size = PROCFS_NOTELEN;
406 1.13 ws break;
407 1.13 ws
408 1.9 cgd case Pnotepg:
409 1.9 cgd break;
410 1.1 pk
411 1.9 cgd default:
412 1.12 ws panic("procfs_getattr type");
413 1.1 pk }
414 1.1 pk
415 1.9 cgd return (error);
416 1.1 pk }
417 1.1 pk
418 1.9 cgd procfs_setattr(vp, vap, cred, p)
419 1.5 pk struct vnode *vp;
420 1.5 pk struct vattr *vap;
421 1.5 pk struct ucred *cred;
422 1.5 pk struct proc *p;
423 1.5 pk {
424 1.5 pk /*
425 1.9 cgd * just fake out attribute setting
426 1.9 cgd * it's not good to generate an error
427 1.9 cgd * return, otherwise things like creat()
428 1.9 cgd * will fail when they try to set the
429 1.9 cgd * file length to 0. worse, this means
430 1.9 cgd * that echo $note > /proc/$pid/note will fail.
431 1.5 pk */
432 1.5 pk
433 1.9 cgd return (0);
434 1.5 pk }
435 1.5 pk
436 1.9 cgd /*
437 1.9 cgd * implement access checking.
438 1.9 cgd *
439 1.9 cgd * something very similar to this code is duplicated
440 1.9 cgd * throughout the 4bsd kernel and should be moved
441 1.9 cgd * into kern/vfs_subr.c sometime.
442 1.9 cgd *
443 1.9 cgd * actually, the check for super-user is slightly
444 1.9 cgd * broken since it will allow read access to write-only
445 1.9 cgd * objects. this doesn't cause any particular trouble
446 1.9 cgd * but does mean that the i/o entry points need to check
447 1.9 cgd * that the operation really does make sense.
448 1.9 cgd */
449 1.9 cgd procfs_access(vp, mode, cred, p)
450 1.1 pk struct vnode *vp;
451 1.1 pk int mode;
452 1.1 pk struct ucred *cred;
453 1.1 pk struct proc *p;
454 1.1 pk {
455 1.9 cgd struct vattr *vap;
456 1.1 pk struct vattr vattr;
457 1.1 pk int error;
458 1.1 pk
459 1.1 pk /*
460 1.1 pk * If you're the super-user,
461 1.1 pk * you always get access.
462 1.1 pk */
463 1.9 cgd if (cred->cr_uid == (uid_t) 0)
464 1.1 pk return (0);
465 1.1 pk vap = &vattr;
466 1.9 cgd if (error = VOP_GETATTR(vp, vap, cred, p))
467 1.1 pk return (error);
468 1.9 cgd
469 1.1 pk /*
470 1.1 pk * Access check is based on only one of owner, group, public.
471 1.1 pk * If not owner, then check group. If not a member of the
472 1.1 pk * group, then check public access.
473 1.1 pk */
474 1.1 pk if (cred->cr_uid != vap->va_uid) {
475 1.9 cgd gid_t *gp;
476 1.9 cgd int i;
477 1.9 cgd
478 1.1 pk mode >>= 3;
479 1.1 pk gp = cred->cr_groups;
480 1.1 pk for (i = 0; i < cred->cr_ngroups; i++, gp++)
481 1.1 pk if (vap->va_gid == *gp)
482 1.1 pk goto found;
483 1.1 pk mode >>= 3;
484 1.1 pk found:
485 1.1 pk ;
486 1.1 pk }
487 1.9 cgd
488 1.9 cgd if ((vap->va_mode & mode) == mode)
489 1.1 pk return (0);
490 1.9 cgd
491 1.1 pk return (EACCES);
492 1.1 pk }
493 1.1 pk
494 1.1 pk /*
495 1.9 cgd * lookup. this is incredibly complicated in the
496 1.9 cgd * general case, however for most pseudo-filesystems
497 1.9 cgd * very little needs to be done.
498 1.9 cgd *
499 1.9 cgd * (dvp) is the directory in which the lookup takes place.
500 1.9 cgd * (ndp) contains all the information about the type of
501 1.9 cgd * lookup being done.
502 1.9 cgd *
503 1.9 cgd * (dvp) is locked on entry.
504 1.9 cgd * the job of lookup is to set ndp->ni_dvp, and ndp->ni_vp.
505 1.9 cgd * (this changes in 4.4 where all we want is the equivalent
506 1.9 cgd * of ndp->ni_vp.)
507 1.9 cgd *
508 1.9 cgd * unless you want to get a migraine, just make sure your
509 1.9 cgd * filesystem doesn't do any locking of its own. otherwise
510 1.9 cgd * read and inwardly digest ufs_lookup().
511 1.9 cgd */
512 1.9 cgd procfs_lookup(dvp, ndp, p)
513 1.9 cgd struct vnode *dvp;
514 1.9 cgd struct nameidata *ndp;
515 1.1 pk struct proc *p;
516 1.1 pk {
517 1.9 cgd char *pname = ndp->ni_ptr;
518 1.9 cgd int error = 0;
519 1.9 cgd int flag;
520 1.1 pk pid_t pid;
521 1.1 pk struct vnode *nvp;
522 1.9 cgd struct pfsnode *pfs;
523 1.1 pk struct proc *procp;
524 1.9 cgd int mode;
525 1.9 cgd pfstype pfs_type;
526 1.9 cgd int i;
527 1.1 pk
528 1.9 cgd if (ndp->ni_namelen == 1 && *pname == '.') {
529 1.9 cgd ndp->ni_vp = dvp;
530 1.9 cgd ndp->ni_dvp = dvp;
531 1.9 cgd VREF(dvp);
532 1.9 cgd return (0);
533 1.9 cgd }
534 1.1 pk
535 1.9 cgd ndp->ni_dvp = dvp;
536 1.1 pk ndp->ni_vp = NULL;
537 1.1 pk
538 1.9 cgd pfs = VTOPFS(dvp);
539 1.9 cgd switch (pfs->pfs_type) {
540 1.9 cgd case Proot:
541 1.9 cgd if (ndp->ni_isdotdot)
542 1.9 cgd return (EIO);
543 1.9 cgd
544 1.12 ws if (NDEQ(ndp, "curproc", 7)) {
545 1.12 ws if (error = procfs_allocvp(dvp->v_mount, &nvp, 1, Proot))
546 1.12 ws return error;
547 1.12 ws ndp->ni_vp = nvp;
548 1.12 ws return 0;
549 1.12 ws }
550 1.12 ws
551 1.12 ws pid = atopid(pname, ndp->ni_namelen);
552 1.9 cgd if (pid == NO_PID)
553 1.9 cgd return (ENOENT);
554 1.9 cgd
555 1.9 cgd procp = PFIND(pid);
556 1.9 cgd if (procp == 0)
557 1.9 cgd return (ENOENT);
558 1.9 cgd
559 1.9 cgd error = procfs_allocvp(dvp->v_mount, &nvp, pid, Pproc);
560 1.9 cgd if (error)
561 1.9 cgd return (error);
562 1.9 cgd
563 1.9 cgd ndp->ni_vp = nvp;
564 1.9 cgd return (0);
565 1.9 cgd
566 1.9 cgd case Pproc:
567 1.9 cgd if (ndp->ni_isdotdot) {
568 1.9 cgd ndp->ni_dvp = dvp;
569 1.9 cgd error = procfs_root(dvp->v_mount, &ndp->ni_vp);
570 1.9 cgd return (error);
571 1.9 cgd }
572 1.1 pk
573 1.9 cgd procp = PFIND(pfs->pfs_pid);
574 1.9 cgd if (procp == 0)
575 1.9 cgd return (ENOENT);
576 1.9 cgd
577 1.9 cgd for (i = 0; i < Nprocent; i++) {
578 1.9 cgd struct pfsnames *dp = &procent[i];
579 1.9 cgd
580 1.9 cgd if (ndp->ni_namelen == dp->d_namlen &&
581 1.18 cgd bcmp(pname, dp->d_name, dp->d_namlen) == 0 &&
582 1.18 cgd (dp->d_valid == NULL || (*dp->d_valid)(procp))) {
583 1.9 cgd pfs_type = dp->d_pfstype;
584 1.9 cgd goto found;
585 1.9 cgd }
586 1.9 cgd }
587 1.9 cgd return (ENOENT);
588 1.1 pk
589 1.9 cgd found:
590 1.9 cgd if (pfs_type == Pfile) {
591 1.9 cgd nvp = procfs_findtextvp(procp);
592 1.9 cgd if (nvp) {
593 1.9 cgd VREF(nvp);
594 1.9 cgd VOP_LOCK(nvp);
595 1.9 cgd } else {
596 1.9 cgd error = ENXIO;
597 1.9 cgd }
598 1.9 cgd } else {
599 1.9 cgd error = procfs_allocvp(dvp->v_mount, &nvp,
600 1.9 cgd pfs->pfs_pid, pfs_type);
601 1.9 cgd if (error)
602 1.9 cgd return (error);
603 1.1 pk
604 1.9 cgd pfs = VTOPFS(nvp);
605 1.9 cgd }
606 1.9 cgd ndp->ni_vp = nvp;
607 1.9 cgd return (error);
608 1.1 pk
609 1.9 cgd default:
610 1.9 cgd return (ENOTDIR);
611 1.1 pk }
612 1.1 pk }
613 1.1 pk
614 1.18 cgd /* check to see if we should display the 'file' entry */
615 1.18 cgd int
616 1.18 cgd procfs_validfile(procp)
617 1.18 cgd struct proc *procp;
618 1.18 cgd {
619 1.18 cgd return (procfs_findtextvp(procp) != NULL);
620 1.18 cgd }
621 1.18 cgd
622 1.9 cgd /*
623 1.9 cgd * readdir returns directory entries from pfsnode (vp).
624 1.9 cgd *
625 1.9 cgd * the strategy here with procfs is to generate a single
626 1.9 cgd * directory entry at a time (struct pfsdent) and then
627 1.9 cgd * copy that out to userland using uiomove. a more efficent
628 1.9 cgd * though more complex implementation, would try to minimize
629 1.9 cgd * the number of calls to uiomove(). for procfs, this is
630 1.9 cgd * hardly worth the added code complexity.
631 1.9 cgd *
632 1.9 cgd * this should just be done through read()
633 1.9 cgd */
634 1.9 cgd procfs_readdir(vp, uio, cred, eofflagp, cookies, ncookies)
635 1.1 pk struct vnode *vp;
636 1.9 cgd struct uio *uio;
637 1.1 pk struct ucred *cred;
638 1.1 pk int *eofflagp;
639 1.6 ws u_int *cookies;
640 1.6 ws int ncookies;
641 1.1 pk {
642 1.9 cgd struct pfsdent d;
643 1.9 cgd struct pfsdent *dp = &d;
644 1.9 cgd struct pfsnode *pfs;
645 1.9 cgd int error;
646 1.9 cgd int count;
647 1.9 cgd int i;
648 1.9 cgd
649 1.13 ws /*
650 1.13 ws * NFS mounting of procfs doesn't work correctly.
651 1.13 ws * The files in procfs are more similar to devices
652 1.13 ws * than to regular files.
653 1.13 ws * See also procfs_vptofh & procfs_fhtovp in procfs_vfsops.c
654 1.13 ws */
655 1.13 ws if (cookies)
656 1.13 ws panic("procfs_readdir");
657 1.13 ws
658 1.9 cgd pfs = VTOPFS(vp);
659 1.1 pk
660 1.9 cgd if (uio->uio_resid < UIO_MX)
661 1.9 cgd return (EINVAL);
662 1.9 cgd if (uio->uio_offset & (UIO_MX-1))
663 1.9 cgd return (EINVAL);
664 1.9 cgd if (uio->uio_offset < 0)
665 1.1 pk return (EINVAL);
666 1.1 pk
667 1.9 cgd error = 0;
668 1.1 pk count = 0;
669 1.9 cgd i = uio->uio_offset / UIO_MX;
670 1.9 cgd
671 1.9 cgd switch (pfs->pfs_type) {
672 1.9 cgd /*
673 1.9 cgd * this is for the process-specific sub-directories.
674 1.9 cgd * all that is needed to is copy out all the entries
675 1.9 cgd * from the procent[] table (top of this file).
676 1.9 cgd */
677 1.9 cgd case Pproc: {
678 1.12 ws while (uio->uio_resid >= UIO_MX && (!cookies || ncookies > 0)) {
679 1.9 cgd struct pfsnames *dt;
680 1.12 ws pid_t pid = pfs->pfs_pid;
681 1.18 cgd struct proc *procp = PFIND(pid);
682 1.9 cgd
683 1.18 cgd if (procp == NULL || i >= Nprocent) {
684 1.9 cgd *eofflagp = 1;
685 1.9 cgd break;
686 1.9 cgd }
687 1.9 cgd
688 1.9 cgd dt = &procent[i];
689 1.9 cgd dp->d_reclen = UIO_MX;
690 1.12 ws
691 1.12 ws if (dt->d_pfstype == Proot)
692 1.12 ws pid = 0;
693 1.12 ws dp->d_fileno = PROCFS_FILENO(pid, dt->d_pfstype);
694 1.15 ws
695 1.18 cgd if (dt->d_valid != NULL && !(*dt->d_valid)(procp))
696 1.18 cgd dp->d_fileno = 0;
697 1.15 ws
698 1.9 cgd dp->d_namlen = dt->d_namlen;
699 1.9 cgd bcopy(dt->d_name, dp->d_name, sizeof(dt->d_name)-1);
700 1.9 cgd error = uiomove((caddr_t) dp, UIO_MX, uio);
701 1.9 cgd if (error)
702 1.9 cgd break;
703 1.9 cgd count += UIO_MX;
704 1.9 cgd i++;
705 1.12 ws if (cookies) {
706 1.12 ws *cookies++ = i * UIO_MX;
707 1.12 ws ncookies--;
708 1.12 ws }
709 1.6 ws }
710 1.9 cgd
711 1.9 cgd break;
712 1.9 cgd
713 1.9 cgd }
714 1.9 cgd
715 1.9 cgd /*
716 1.9 cgd * this is for the root of the procfs filesystem
717 1.9 cgd * what is needed is a special entry for "curproc"
718 1.9 cgd * followed by an entry for each process on allproc
719 1.9 cgd #ifdef PROCFS_ZOMBIE
720 1.9 cgd * and zombproc.
721 1.9 cgd #endif
722 1.9 cgd */
723 1.9 cgd
724 1.9 cgd case Proot: {
725 1.9 cgd int pcnt;
726 1.9 cgd #ifdef PROCFS_ZOMBIE
727 1.9 cgd int doingzomb = 0;
728 1.9 cgd #endif
729 1.9 cgd struct proc *p;
730 1.9 cgd
731 1.10 cgd p = (struct proc *) allproc;
732 1.9 cgd
733 1.9 cgd pcnt = PROCFS_XFILES;
734 1.9 cgd
735 1.12 ws while (p && uio->uio_resid >= UIO_MX && (!cookies || ncookies > 0)) {
736 1.9 cgd bzero((char *) dp, UIO_MX);
737 1.9 cgd dp->d_reclen = UIO_MX;
738 1.9 cgd
739 1.9 cgd switch (i) {
740 1.12 ws case 0: /* `.' */
741 1.12 ws case 1: /* `..' */
742 1.12 ws dp->d_fileno = PROCFS_FILENO(0, Proot);
743 1.12 ws bcopy("..",dp->d_name,3);
744 1.12 ws dp->d_namlen = i + 1;
745 1.12 ws dp->d_name[i + 1] = 0;
746 1.12 ws break;
747 1.12 ws case 2:
748 1.9 cgd /* ship out entry for "curproc" */
749 1.12 ws dp->d_fileno = PROCFS_FILENO(1, Proot);
750 1.9 cgd dp->d_namlen = 7;
751 1.9 cgd bcopy("curproc", dp->d_name, dp->d_namlen+1);
752 1.9 cgd break;
753 1.9 cgd
754 1.9 cgd default:
755 1.9 cgd if (pcnt >= i) {
756 1.9 cgd dp->d_fileno = PROCFS_FILENO(p->p_pid, Pproc);
757 1.9 cgd dp->d_namlen = sprintf(dp->d_name, "%ld", (long) p->p_pid);
758 1.9 cgd }
759 1.9 cgd
760 1.20 cgd p = p->p_next;
761 1.9 cgd
762 1.9 cgd #ifdef PROCFS_ZOMBIE
763 1.9 cgd if (p == 0 && doingzomb == 0) {
764 1.9 cgd doingzomb = 1;
765 1.9 cgd p = zombproc;
766 1.9 cgd }
767 1.1 pk #endif
768 1.1 pk
769 1.9 cgd if (pcnt++ < i)
770 1.9 cgd continue;
771 1.9 cgd
772 1.9 cgd break;
773 1.1 pk }
774 1.9 cgd error = uiomove((caddr_t) dp, UIO_MX, uio);
775 1.9 cgd if (error)
776 1.9 cgd break;
777 1.9 cgd count += UIO_MX;
778 1.9 cgd i++;
779 1.12 ws if (cookies) {
780 1.12 ws *cookies++ = i * UIO_MX;
781 1.12 ws ncookies--;
782 1.12 ws }
783 1.1 pk }
784 1.1 pk
785 1.9 cgd break;
786 1.9 cgd
787 1.9 cgd }
788 1.9 cgd
789 1.9 cgd default:
790 1.9 cgd error = ENOTDIR;
791 1.9 cgd break;
792 1.1 pk }
793 1.9 cgd
794 1.9 cgd uio->uio_offset = i * UIO_MX;
795 1.1 pk if (count == 0)
796 1.1 pk *eofflagp = 1;
797 1.1 pk
798 1.9 cgd return (error);
799 1.12 ws }
800 1.12 ws
801 1.12 ws /*
802 1.12 ws * readlink reads the link of "curproc"
803 1.12 ws */
804 1.12 ws procfs_readlink(vp, uio, cred)
805 1.12 ws struct vnode *vp;
806 1.12 ws struct uio *uio;
807 1.12 ws struct ucred *cred;
808 1.12 ws {
809 1.12 ws struct pfsnode *pfs = VTOPFS(vp);
810 1.12 ws char buf[16]; /* should be enough */
811 1.12 ws int len;
812 1.12 ws
813 1.12 ws if (pfs->pfs_fileno != PROCFS_FILENO(1,Proot))
814 1.12 ws return EINVAL;
815 1.12 ws
816 1.12 ws len = sprintf(buf,"%ld",(long)curproc->p_pid);
817 1.12 ws
818 1.12 ws return uiomove(buf, len, uio);
819 1.1 pk }
820 1.1 pk
821 1.1 pk /*
822 1.9 cgd * convert decimal ascii to pid_t
823 1.1 pk */
824 1.9 cgd static pid_t
825 1.9 cgd atopid(b, len)
826 1.9 cgd const char *b;
827 1.9 cgd u_int len;
828 1.1 pk {
829 1.9 cgd pid_t p = 0;
830 1.1 pk
831 1.1 pk while (len--) {
832 1.9 cgd char c = *b++;
833 1.1 pk if (c < '0' || c > '9')
834 1.9 cgd return (NO_PID);
835 1.9 cgd p = 10 * p + (c - '0');
836 1.9 cgd if (p > PID_MAX)
837 1.9 cgd return (NO_PID);
838 1.1 pk }
839 1.9 cgd
840 1.9 cgd return (p);
841 1.1 pk }
842 1.9 cgd
843 1.9 cgd /*
844 1.9 cgd * procfs vnode operations.
845 1.9 cgd */
846 1.9 cgd struct vnodeops procfs_vnodeops = {
847 1.9 cgd procfs_lookup, /* lookup */
848 1.9 cgd procfs_create, /* create */
849 1.9 cgd procfs_mknod, /* mknod */
850 1.9 cgd procfs_open, /* open */
851 1.9 cgd procfs_close, /* close */
852 1.9 cgd procfs_access, /* access */
853 1.9 cgd procfs_getattr, /* getattr */
854 1.9 cgd procfs_setattr, /* setattr */
855 1.9 cgd procfs_read, /* read */
856 1.9 cgd procfs_write, /* write */
857 1.9 cgd procfs_ioctl, /* ioctl */
858 1.9 cgd procfs_select, /* select */
859 1.9 cgd procfs_mmap, /* mmap */
860 1.9 cgd procfs_fsync, /* fsync */
861 1.9 cgd procfs_seek, /* seek */
862 1.9 cgd procfs_remove, /* remove */
863 1.9 cgd procfs_link, /* link */
864 1.9 cgd procfs_rename, /* rename */
865 1.9 cgd procfs_mkdir, /* mkdir */
866 1.9 cgd procfs_rmdir, /* rmdir */
867 1.9 cgd procfs_symlink, /* symlink */
868 1.9 cgd procfs_readdir, /* readdir */
869 1.9 cgd procfs_readlink, /* readlink */
870 1.9 cgd procfs_abortop, /* abortop */
871 1.9 cgd procfs_inactive, /* inactive */
872 1.9 cgd procfs_reclaim, /* reclaim */
873 1.9 cgd procfs_lock, /* lock */
874 1.9 cgd procfs_unlock, /* unlock */
875 1.9 cgd procfs_bmap, /* bmap */
876 1.9 cgd procfs_strategy, /* strategy */
877 1.9 cgd procfs_print, /* print */
878 1.9 cgd procfs_islocked, /* islocked */
879 1.9 cgd procfs_advlock, /* advlock */
880 1.9 cgd };
881