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