procfs_vnops.c revision 1.2 1 1.1 pk /*
2 1.2 pk * Copyright (c) 1993 Paul Kranenburg
3 1.2 pk * All rights reserved.
4 1.2 pk *
5 1.2 pk * Redistribution and use in source and binary forms, with or without
6 1.2 pk * modification, are permitted provided that the following conditions
7 1.2 pk * are met:
8 1.2 pk * 1. Redistributions of source code must retain the above copyright
9 1.2 pk * notice, this list of conditions and the following disclaimer.
10 1.2 pk * 2. Redistributions in binary form must reproduce the above copyright
11 1.2 pk * notice, this list of conditions and the following disclaimer in the
12 1.2 pk * documentation and/or other materials provided with the distribution.
13 1.2 pk * 3. All advertising materials mentioning features or use of this software
14 1.2 pk * must display the following acknowledgement:
15 1.2 pk * This product includes software developed by Christopher G. Demetriou.
16 1.2 pk * 4. The name of the author may not be used to endorse or promote products
17 1.2 pk * derived from this software withough specific prior written permission
18 1.2 pk *
19 1.2 pk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 1.2 pk * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 1.2 pk * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 1.2 pk * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 1.2 pk * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 1.2 pk * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 1.2 pk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 1.2 pk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 1.2 pk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 1.2 pk * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 1.2 pk *
30 1.2 pk * $Id: procfs_vnops.c,v 1.2 1993/08/24 16:25:13 pk Exp $
31 1.2 pk */
32 1.2 pk
33 1.2 pk /*
34 1.2 pk * PROCFS vnode interface routines
35 1.1 pk */
36 1.1 pk
37 1.1 pk #include "param.h"
38 1.1 pk #include "systm.h"
39 1.1 pk #include "time.h"
40 1.1 pk #include "kernel.h"
41 1.1 pk #include "ioctl.h"
42 1.1 pk #include "file.h"
43 1.1 pk #include "proc.h"
44 1.1 pk #include "buf.h"
45 1.1 pk #include "vnode.h"
46 1.1 pk #include "namei.h"
47 1.1 pk #include "resourcevar.h"
48 1.1 pk #include "vm/vm.h"
49 1.1 pk #include "kinfo.h"
50 1.1 pk #include "kinfo_proc.h"
51 1.1 pk
52 1.1 pk #include "procfs.h"
53 1.1 pk #include "pfsnode.h"
54 1.1 pk
55 1.1 pk #include "machine/vmparam.h"
56 1.1 pk
57 1.1 pk /*
58 1.1 pk * procfs vnode operations.
59 1.1 pk */
60 1.1 pk struct vnodeops pfs_vnodeops = {
61 1.1 pk pfs_lookup, /* lookup */
62 1.1 pk pfs_create, /* create */
63 1.1 pk pfs_mknod, /* mknod */
64 1.1 pk pfs_open, /* open */
65 1.1 pk pfs_close, /* close */
66 1.1 pk pfs_access, /* access */
67 1.1 pk pfs_getattr, /* getattr */
68 1.1 pk pfs_setattr, /* setattr */
69 1.1 pk pfs_read, /* read */
70 1.1 pk pfs_write, /* write */
71 1.1 pk pfs_ioctl, /* ioctl */
72 1.1 pk pfs_select, /* select */
73 1.1 pk pfs_mmap, /* mmap */
74 1.1 pk pfs_fsync, /* fsync */
75 1.1 pk pfs_seek, /* seek */
76 1.1 pk pfs_remove, /* remove */
77 1.1 pk pfs_link, /* link */
78 1.1 pk pfs_rename, /* rename */
79 1.1 pk pfs_mkdir, /* mkdir */
80 1.1 pk pfs_rmdir, /* rmdir */
81 1.1 pk pfs_symlink, /* symlink */
82 1.1 pk pfs_readdir, /* readdir */
83 1.1 pk pfs_readlink, /* readlink */
84 1.1 pk pfs_abortop, /* abortop */
85 1.1 pk pfs_inactive, /* inactive */
86 1.1 pk pfs_reclaim, /* reclaim */
87 1.1 pk pfs_lock, /* lock */
88 1.1 pk pfs_unlock, /* unlock */
89 1.1 pk pfs_bmap, /* bmap */
90 1.1 pk pfs_strategy, /* strategy */
91 1.1 pk pfs_print, /* print */
92 1.1 pk pfs_islocked, /* islocked */
93 1.1 pk pfs_advlock, /* advlock */
94 1.1 pk };
95 1.1 pk
96 1.1 pk /*
97 1.1 pk * Vnode Operations.
98 1.1 pk *
99 1.1 pk */
100 1.1 pk /* ARGSUSED */
101 1.1 pk int
102 1.1 pk pfs_open(vp, mode, cred, p)
103 1.1 pk register struct vnode *vp;
104 1.1 pk int mode;
105 1.1 pk struct ucred *cred;
106 1.1 pk struct proc *p;
107 1.1 pk {
108 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
109 1.1 pk
110 1.1 pk #ifdef DEBUG
111 1.1 pk if (pfs_debug)
112 1.1 pk printf("pfs_open: vp 0x%x, proc %d\n", vp, p->p_pid);
113 1.1 pk #endif
114 1.1 pk
115 1.1 pk if ((pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0) == NULL)
116 1.1 pk return ESRCH;
117 1.1 pk
118 1.1 pk if ( (pfsp->flags & FWRITE) && (mode & O_EXCL) ||
119 1.1 pk (pfsp->flags & O_EXCL) && (mode & FWRITE) )
120 1.1 pk return EBUSY;
121 1.1 pk
122 1.1 pk
123 1.1 pk if (mode & FWRITE)
124 1.1 pk pfsp->flags = (mode & (FWRITE|O_EXCL));
125 1.1 pk return 0;
126 1.1 pk }
127 1.1 pk
128 1.1 pk /*
129 1.1 pk * /proc filesystem close routine
130 1.1 pk */
131 1.1 pk /* ARGSUSED */
132 1.1 pk int
133 1.1 pk pfs_close(vp, flag, cred, p)
134 1.1 pk register struct vnode *vp;
135 1.1 pk int flag;
136 1.1 pk struct ucred *cred;
137 1.1 pk struct proc *p;
138 1.1 pk {
139 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
140 1.1 pk
141 1.1 pk #ifdef DEBUG
142 1.1 pk if (pfs_debug)
143 1.1 pk printf("pfs_close: vp 0x%x proc %d\n", vp, p->p_pid);
144 1.1 pk #endif
145 1.1 pk if ((flag & FWRITE) && (pfsp->flags & O_EXCL))
146 1.1 pk pfsp->flags &= ~(FWRITE|O_EXCL);
147 1.1 pk
148 1.1 pk return (0);
149 1.1 pk }
150 1.1 pk
151 1.1 pk /*
152 1.1 pk * Ioctl operation.
153 1.1 pk */
154 1.1 pk /* ARGSUSED */
155 1.1 pk int
156 1.1 pk pfs_ioctl(vp, com, data, fflag, cred, p)
157 1.1 pk struct vnode *vp;
158 1.1 pk int com;
159 1.1 pk caddr_t data;
160 1.1 pk int fflag;
161 1.1 pk struct ucred *cred;
162 1.1 pk struct proc *p;
163 1.1 pk {
164 1.1 pk int error = 0;
165 1.1 pk struct proc *procp;
166 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
167 1.1 pk
168 1.1 pk procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
169 1.1 pk if (!procp)
170 1.1 pk return ESRCH;
171 1.1 pk
172 1.1 pk switch (com) {
173 1.1 pk
174 1.1 pk case PIOCGPINFO: {
175 1.1 pk int copysize = sizeof(struct kinfo_proc), needed;
176 1.1 pk kinfo_doproc(KINFO_PROC_PID, data, ©size,
177 1.1 pk pfsp->pfs_pid, &needed);
178 1.1 pk break;
179 1.1 pk }
180 1.1 pk
181 1.1 pk #ifdef notyet /* Changes to proc.h needed */
182 1.1 pk case PIOCGSIGSET:
183 1.1 pk procp->p_psigset = *(sigset_t *)data;
184 1.1 pk break;
185 1.1 pk
186 1.1 pk case PIOCSSIGSET:
187 1.1 pk *(sigset_t *)data = procp->p_psigset;
188 1.1 pk break;
189 1.1 pk
190 1.1 pk case PIOCGFLTSET:
191 1.1 pk procp->p_pfltset = *(sigflt_t *)data;
192 1.1 pk break;
193 1.1 pk
194 1.1 pk case PIOCSFLTSET:
195 1.1 pk *(fltset_t *)data = procp->p_pfltset;
196 1.1 pk break;
197 1.1 pk #endif
198 1.1 pk
199 1.1 pk case PIOCGMAPFD:
200 1.1 pk error = pfs_vmfd(procp, pfsp, (struct vmfd *)data, p);
201 1.1 pk break;
202 1.1 pk
203 1.1 pk case PIOCGNMAP:
204 1.1 pk *(int *)data = pfs_vm_nentries(procp, pfsp);
205 1.1 pk break;
206 1.1 pk
207 1.1 pk case PIOCGMAP:
208 1.1 pk error = pfs_vmmap(procp, pfsp, *(struct procmap *)data);
209 1.1 pk break;
210 1.1 pk
211 1.1 pk default:
212 1.1 pk error = EIO;
213 1.1 pk break;
214 1.1 pk }
215 1.1 pk return error;
216 1.1 pk }
217 1.1 pk
218 1.1 pk /*
219 1.1 pk * Pass I/O requests to the memory filesystem process.
220 1.1 pk */
221 1.1 pk int
222 1.1 pk pfs_strategy(bp)
223 1.1 pk register struct buf *bp;
224 1.1 pk {
225 1.1 pk struct vnode *vp;
226 1.1 pk struct proc *p = curproc; /* XXX */
227 1.1 pk
228 1.1 pk return (0);
229 1.1 pk }
230 1.1 pk
231 1.1 pk /*
232 1.1 pk * This is a noop, simply returning what one has been given.
233 1.1 pk */
234 1.1 pk int
235 1.1 pk pfs_bmap(vp, bn, vpp, bnp)
236 1.1 pk struct vnode *vp;
237 1.1 pk daddr_t bn;
238 1.1 pk struct vnode **vpp;
239 1.1 pk daddr_t *bnp;
240 1.1 pk {
241 1.1 pk
242 1.1 pk if (vpp != NULL)
243 1.1 pk *vpp = vp;
244 1.1 pk if (bnp != NULL)
245 1.1 pk *bnp = bn;
246 1.1 pk return (0);
247 1.1 pk }
248 1.1 pk
249 1.1 pk /*
250 1.1 pk * /proc filesystem inactive routine
251 1.1 pk */
252 1.1 pk /* ARGSUSED */
253 1.1 pk int
254 1.1 pk pfs_inactive(vp, p)
255 1.1 pk struct vnode *vp;
256 1.1 pk struct proc *p;
257 1.1 pk {
258 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
259 1.1 pk
260 1.1 pk #if 0
261 1.1 pk if ((pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0) && vp->v_usecount == 0)
262 1.1 pk vgone(vp);
263 1.1 pk #endif
264 1.1 pk if (vp->v_usecount == 0)
265 1.1 pk vgone(vp);
266 1.1 pk return 0;
267 1.1 pk }
268 1.1 pk
269 1.1 pk /*
270 1.1 pk * /proc filesystem reclaim routine
271 1.1 pk */
272 1.1 pk /* ARGSUSED */
273 1.1 pk int
274 1.1 pk pfs_reclaim(vp)
275 1.1 pk struct vnode *vp;
276 1.1 pk {
277 1.1 pk struct pfsnode **pp, *pfsp = VTOPFS(vp);
278 1.1 pk
279 1.1 pk for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next) {
280 1.1 pk if (*pp == pfsp) {
281 1.1 pk *pp = pfsp->pfs_next;
282 1.1 pk break;
283 1.1 pk }
284 1.1 pk }
285 1.1 pk return 0;
286 1.1 pk }
287 1.1 pk
288 1.1 pk /*
289 1.1 pk * Print out the contents of an pfsnode.
290 1.1 pk */
291 1.1 pk void
292 1.1 pk pfs_print(vp)
293 1.1 pk struct vnode *vp;
294 1.1 pk {
295 1.1 pk return;
296 1.1 pk }
297 1.1 pk
298 1.1 pk /*
299 1.1 pk * /proc bad operation
300 1.1 pk */
301 1.1 pk int
302 1.1 pk pfs_badop()
303 1.1 pk {
304 1.1 pk printf("pfs_badop called\n");
305 1.1 pk return EIO;
306 1.1 pk }
307 1.1 pk
308 1.1 pk #if 0 /* Moved to pfs_subr.c */
309 1.1 pk /*
310 1.1 pk * Vnode op for reading/writing.
311 1.1 pk */
312 1.1 pk /* ARGSUSED */
313 1.1 pk int
314 1.1 pk pfs_doio(vp, uio, ioflag, cred)
315 1.1 pk struct vnode *vp;
316 1.1 pk register struct uio *uio;
317 1.1 pk int ioflag;
318 1.1 pk struct ucred *cred;
319 1.1 pk {
320 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
321 1.1 pk struct proc *procp;
322 1.1 pk int error = 0;
323 1.1 pk long n, off;
324 1.1 pk caddr_t kva;
325 1.1 pk
326 1.1 pk #ifdef DEBUG
327 1.1 pk if (pfs_debug)
328 1.1 pk printf("pfs_doio(%s): vp 0x%x, proc %x\n",
329 1.1 pk uio->uio_rw==UIO_READ?"R":"W", vp, uio->uio_procp);
330 1.1 pk #endif
331 1.1 pk
332 1.1 pk #ifdef DIAGNOSTIC
333 1.1 pk if (vp->v_type != VPROC)
334 1.1 pk panic("pfs_doio vtype");
335 1.1 pk #endif
336 1.1 pk procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
337 1.1 pk if (!procp)
338 1.1 pk return ESRCH;
339 1.1 pk
340 1.1 pk if (uio->uio_resid == 0)
341 1.1 pk return (0);
342 1.1 pk if (uio->uio_offset < 0)
343 1.1 pk return (EINVAL);
344 1.1 pk
345 1.1 pk do { /* One page at a time */
346 1.1 pk off = uio->uio_offset - trunc_page(uio->uio_offset);
347 1.1 pk n = MIN(PAGE_SIZE-off, uio->uio_resid);
348 1.1 pk
349 1.1 pk /* Map page into kernel space */
350 1.1 pk error = pfs_map(procp, &kva, uio->uio_rw, uio->uio_offset);
351 1.1 pk if (error)
352 1.1 pk return error;
353 1.1 pk
354 1.1 pk error = uiomove(kva + off, (int)n, uio);
355 1.1 pk pfs_unmap(procp, kva);
356 1.1 pk
357 1.1 pk } while (error == 0 && uio->uio_resid > 0);
358 1.1 pk
359 1.1 pk return (error);
360 1.1 pk }
361 1.1 pk #endif
362 1.1 pk
363 1.1 pk /*
364 1.1 pk * Make up some attributes for a process file
365 1.1 pk */
366 1.1 pk int
367 1.1 pk pfs_getattr (vp, vap, cred, p)
368 1.1 pk struct vnode *vp;
369 1.1 pk struct vattr *vap;
370 1.1 pk struct ucred *cred;
371 1.1 pk struct proc *p;
372 1.1 pk {
373 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
374 1.1 pk struct proc *procp;
375 1.1 pk
376 1.1 pk VATTR_NULL(vap);
377 1.1 pk vap->va_type = vp->v_type;
378 1.1 pk
379 1.1 pk if (vp->v_flag & VROOT) {
380 1.1 pk vap->va_mode = 0755;
381 1.1 pk vap->va_nlink = 2;
382 1.1 pk vap->va_size =
383 1.1 pk roundup((2+nprocs)*sizeof(struct pfsdent), DIRBLKSIZ);
384 1.1 pk vap->va_size_rsv = 0;
385 1.1 pk vap->va_uid = 0;
386 1.1 pk vap->va_gid = 0;
387 1.1 pk vap->va_atime = vap->va_mtime = vap->va_ctime = time; /*XXX*/
388 1.1 pk return 0;
389 1.1 pk }
390 1.1 pk
391 1.1 pk procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
392 1.1 pk if (!procp)
393 1.1 pk return ESRCH;
394 1.1 pk
395 1.1 pk vap->va_mode = 0700;
396 1.1 pk vap->va_nlink = 1;
397 1.1 pk vap->va_size = ctob( procp->p_vmspace->vm_tsize +
398 1.1 pk procp->p_vmspace->vm_dsize +
399 1.1 pk procp->p_vmspace->vm_ssize);
400 1.1 pk vap->va_size_rsv = 0;
401 1.1 pk vap->va_blocksize = page_size;
402 1.1 pk vap->va_uid = procp->p_ucred->cr_uid;
403 1.1 pk vap->va_gid = procp->p_ucred->cr_gid;
404 1.1 pk if (vap->va_uid != procp->p_cred->p_ruid)
405 1.1 pk vap->va_mode |= VSUID;
406 1.1 pk if (vap->va_gid != procp->p_cred->p_rgid)
407 1.1 pk vap->va_mode |= VSGID;
408 1.1 pk if (procp->p_flag & SLOAD) {
409 1.1 pk vap->va_atime = vap->va_mtime = vap->va_ctime =
410 1.1 pk procp->p_stats->p_start;
411 1.1 pk }
412 1.1 pk
413 1.1 pk return 0;
414 1.1 pk }
415 1.1 pk
416 1.1 pk int
417 1.1 pk pfs_access (vp, mode, cred, p)
418 1.1 pk struct vnode *vp;
419 1.1 pk int mode;
420 1.1 pk struct ucred *cred;
421 1.1 pk struct proc *p;
422 1.1 pk {
423 1.1 pk register struct vattr *vap;
424 1.1 pk register gid_t *gp;
425 1.1 pk struct vattr vattr;
426 1.1 pk register int i;
427 1.1 pk int error;
428 1.1 pk
429 1.1 pk /*
430 1.1 pk * If you're the super-user,
431 1.1 pk * you always get access.
432 1.1 pk */
433 1.1 pk if (cred->cr_uid == 0)
434 1.1 pk return (0);
435 1.1 pk vap = &vattr;
436 1.1 pk if (error = pfs_getattr(vp, vap, cred, p))
437 1.1 pk return (error);
438 1.1 pk /*
439 1.1 pk * Access check is based on only one of owner, group, public.
440 1.1 pk * If not owner, then check group. If not a member of the
441 1.1 pk * group, then check public access.
442 1.1 pk */
443 1.1 pk if (cred->cr_uid != vap->va_uid) {
444 1.1 pk mode >>= 3;
445 1.1 pk gp = cred->cr_groups;
446 1.1 pk for (i = 0; i < cred->cr_ngroups; i++, gp++)
447 1.1 pk if (vap->va_gid == *gp)
448 1.1 pk goto found;
449 1.1 pk mode >>= 3;
450 1.1 pk found:
451 1.1 pk ;
452 1.1 pk }
453 1.1 pk if ((vap->va_mode & mode) != 0)
454 1.1 pk return (0);
455 1.1 pk return (EACCES);
456 1.1 pk }
457 1.1 pk
458 1.1 pk /*
459 1.1 pk * /proc lookup
460 1.1 pk */
461 1.1 pk int
462 1.1 pk pfs_lookup(vp, ndp, p)
463 1.1 pk register struct vnode *vp;
464 1.1 pk register struct nameidata *ndp;
465 1.1 pk struct proc *p;
466 1.1 pk {
467 1.1 pk int lockparent, wantparent, flag, error = 0;
468 1.1 pk pid_t pid;
469 1.1 pk struct vnode *nvp;
470 1.1 pk struct pfsnode *pfsp;
471 1.1 pk struct proc *procp;
472 1.1 pk
473 1.1 pk #ifdef DEBUG
474 1.1 pk if (pfs_debug)
475 1.1 pk printf("pfs_lookup: vp 0x%x name %s proc %d\n",
476 1.1 pk vp, ndp->ni_ptr, p->p_pid);
477 1.1 pk #endif
478 1.1 pk
479 1.1 pk ndp->ni_dvp = vp;
480 1.1 pk ndp->ni_vp = NULL;
481 1.1 pk if (vp->v_type != VDIR)
482 1.1 pk return (ENOTDIR);
483 1.1 pk
484 1.1 pk lockparent = ndp->ni_nameiop & LOCKPARENT;
485 1.1 pk flag = ndp->ni_nameiop & OPMASK;
486 1.1 pk wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
487 1.1 pk if (flag != LOOKUP)
488 1.1 pk return EACCES;
489 1.1 pk if (ndp->ni_isdotdot) {
490 1.1 pk /* Should not happen */
491 1.1 pk printf("pfs_lookup: vp 0x%x: dotdot\n", vp);
492 1.1 pk return EIO;
493 1.1 pk }
494 1.1 pk if (ndp->ni_namelen == 1 && *ndp->ni_ptr == '.') {
495 1.1 pk VREF(vp);
496 1.1 pk ndp->ni_vp = vp;
497 1.1 pk return 0;
498 1.1 pk }
499 1.1 pk
500 1.1 pk pid = (pid_t)atoi(ndp->ni_ptr, ndp->ni_namelen);
501 1.1 pk if (pid == (pid_t)-1)
502 1.1 pk return ENOENT;
503 1.1 pk
504 1.1 pk if ((procp = pid?pfind(pid):&proc0) == NULL)
505 1.1 pk return ENOENT;
506 1.1 pk
507 1.1 pk for (pfsp = pfshead; pfsp != NULL; pfsp = pfsp->pfs_next) {
508 1.1 pk if (pfsp->pfs_pid == pid)
509 1.1 pk break;
510 1.1 pk }
511 1.1 pk
512 1.1 pk if (pfsp == NULL) {
513 1.1 pk struct pfsnode **pp;
514 1.1 pk error = getnewvnode(VT_PROCFS, vp->v_mount, &pfs_vnodeops, &nvp);
515 1.1 pk if (error)
516 1.1 pk return error;
517 1.1 pk
518 1.1 pk nvp->v_type = VPROC;
519 1.1 pk pfsp = VTOPFS(nvp);
520 1.1 pk pfsp->pfs_pid = pid;
521 1.1 pk pfsp->pfs_vnode = nvp;
522 1.1 pk for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next);
523 1.1 pk *pp = pfsp;
524 1.1 pk
525 1.1 pk }
526 1.1 pk ndp->ni_vp = pfsp->pfs_vnode;
527 1.1 pk
528 1.1 pk return (error);
529 1.1 pk }
530 1.1 pk
531 1.1 pk int
532 1.1 pk pfs_readdir(vp, uio, cred, eofflagp)
533 1.1 pk struct vnode *vp;
534 1.1 pk register struct uio *uio;
535 1.1 pk struct ucred *cred;
536 1.1 pk int *eofflagp;
537 1.1 pk {
538 1.1 pk int error = 0;
539 1.1 pk int count, lost, pcnt, skipcnt, doingzomb = 0;
540 1.1 pk struct proc *p;
541 1.1 pk struct pfsdent dent;
542 1.1 pk
543 1.1 pk #ifdef DEBUG
544 1.1 pk if (pfs_debug)
545 1.1 pk printf("pfs_readdir: vp 0x%x proc %d\n",
546 1.1 pk vp, uio->uio_procp->p_pid);
547 1.1 pk #endif
548 1.1 pk count = uio->uio_resid;
549 1.1 pk count &= ~(DIRBLKSIZ - 1);
550 1.1 pk lost = uio->uio_resid - count;
551 1.1 pk if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
552 1.1 pk return (EINVAL);
553 1.1 pk uio->uio_resid = count;
554 1.1 pk uio->uio_iov->iov_len = count;
555 1.1 pk *eofflagp = 1;
556 1.1 pk skipcnt = uio->uio_offset / sizeof(struct pfsdent);
557 1.1 pk
558 1.1 pk count = 0;
559 1.1 pk if (skipcnt == 0) {
560 1.1 pk /* Fake "." and ".." entries? */
561 1.1 pk #if 1
562 1.1 pk dent.d_fileno = 2; /* XXX - Filesystem root */
563 1.1 pk dent.d_reclen = sizeof(struct pfsdent);
564 1.1 pk
565 1.1 pk dent.d_namlen = 1;
566 1.1 pk dent.d_nam[0] = '.';
567 1.1 pk dent.d_nam[1] = '\0';
568 1.1 pk error = uiomove((char *)&dent, sizeof(struct pfsdent) , uio);
569 1.1 pk if (error)
570 1.1 pk return error;
571 1.1 pk
572 1.1 pk dent.d_fileno = 2;
573 1.1 pk dent.d_namlen = 2;
574 1.1 pk dent.d_nam[1] = '.';
575 1.1 pk dent.d_nam[2] = '\0';
576 1.1 pk error = uiomove((char *)&dent, sizeof(struct pfsdent) , uio);
577 1.1 pk if (error)
578 1.1 pk return error;
579 1.1 pk #endif
580 1.1 pk count += 2*dent.d_reclen;
581 1.1 pk }
582 1.1 pk
583 1.1 pk p = allproc;
584 1.1 pk for (pcnt = 0; p && uio->uio_resid; pcnt++) {
585 1.1 pk if (pcnt < skipcnt) {
586 1.1 pk p = p->p_nxt;
587 1.1 pk if (p == NULL && doingzomb == 0) {
588 1.1 pk doingzomb = 1;
589 1.1 pk p = zombproc;
590 1.1 pk }
591 1.1 pk continue;
592 1.1 pk }
593 1.1 pk *eofflagp = 0;
594 1.1 pk
595 1.1 pk /* "inode" is process slot (actually position on list) */
596 1.1 pk dent.d_fileno = (unsigned long)(pcnt+1);
597 1.1 pk dent.d_namlen = itos((unsigned int)p->p_pid, dent.d_nam);
598 1.1 pk dent.d_nam[dent.d_namlen] = '\0';
599 1.1 pk
600 1.1 pk p = p->p_nxt;
601 1.1 pk if (p == NULL && doingzomb == 0) {
602 1.1 pk doingzomb = 1;
603 1.1 pk p = zombproc;
604 1.1 pk }
605 1.1 pk if (p == NULL) {
606 1.1 pk /* Extend 'reclen' to end of block */;
607 1.1 pk dent.d_reclen = DIRBLKSIZ - (count & (DIRBLKSIZ - 1));
608 1.1 pk } else
609 1.1 pk dent.d_reclen = sizeof(struct pfsdent);
610 1.1 pk count += dent.d_reclen;
611 1.1 pk error = uiomove((char *)&dent, dent.d_reclen, uio);
612 1.1 pk if (error)
613 1.1 pk break;
614 1.1 pk }
615 1.1 pk if (count == 0)
616 1.1 pk *eofflagp = 1;
617 1.1 pk
618 1.1 pk uio->uio_resid += lost;
619 1.1 pk return error;
620 1.1 pk }
621 1.1 pk
622 1.1 pk /*
623 1.1 pk * convert n to decimal representation in character array b
624 1.1 pk * return number of decimal digits produced.
625 1.1 pk */
626 1.1 pk int
627 1.1 pk itos(n, b)
628 1.1 pk unsigned int n;
629 1.1 pk char *b;
630 1.1 pk {
631 1.1 pk #define BASE 10
632 1.1 pk int m = (n<BASE)?0:itos(n/BASE, b);
633 1.1 pk
634 1.1 pk *(b+m) = "0123456789abcdef"[n%BASE];
635 1.1 pk return m+1;
636 1.1 pk }
637 1.1 pk
638 1.1 pk /*
639 1.1 pk * convert decimal ascii representation in b of length len to integer
640 1.1 pk */
641 1.1 pk int
642 1.1 pk atoi(b, len)
643 1.1 pk char *b;
644 1.1 pk unsigned int len;
645 1.1 pk {
646 1.1 pk int n = 0;
647 1.1 pk
648 1.1 pk while (len--) {
649 1.1 pk register char c = *b++;
650 1.1 pk if (c < '0' || c > '9')
651 1.1 pk return -1;
652 1.1 pk n = 10 * n + (c - '0');
653 1.1 pk }
654 1.1 pk return n;
655 1.1 pk }
656