procfs_vnops.c revision 1.6.2.1 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.3 pk * This product includes software developed by Paul Kranenburg.
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.6.2.1 mycroft * $Id: procfs_vnops.c,v 1.6.2.1 1993/09/24 08:53:04 mycroft 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.4 pk if ( (pfsp->pfs_flags & FWRITE) && (mode & O_EXCL) ||
119 1.4 pk (pfsp->pfs_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.4 pk pfsp->pfs_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.4 pk if ((flag & FWRITE) && (pfsp->pfs_flags & O_EXCL))
146 1.4 pk pfsp->pfs_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.5 pk if ((pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0) == NULL
261 1.5 pk && vp->v_usecount == 0)
262 1.1 pk vgone(vp);
263 1.5 pk
264 1.1 pk return 0;
265 1.1 pk }
266 1.1 pk
267 1.1 pk /*
268 1.1 pk * /proc filesystem reclaim routine
269 1.1 pk */
270 1.1 pk /* ARGSUSED */
271 1.1 pk int
272 1.1 pk pfs_reclaim(vp)
273 1.1 pk struct vnode *vp;
274 1.1 pk {
275 1.1 pk struct pfsnode **pp, *pfsp = VTOPFS(vp);
276 1.1 pk
277 1.1 pk for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next) {
278 1.1 pk if (*pp == pfsp) {
279 1.1 pk *pp = pfsp->pfs_next;
280 1.1 pk break;
281 1.1 pk }
282 1.1 pk }
283 1.1 pk return 0;
284 1.1 pk }
285 1.1 pk
286 1.1 pk /*
287 1.1 pk * Print out the contents of an pfsnode.
288 1.1 pk */
289 1.1 pk void
290 1.1 pk pfs_print(vp)
291 1.1 pk struct vnode *vp;
292 1.1 pk {
293 1.5 pk struct pfsnode *pfsp = VTOPFS(vp);
294 1.5 pk
295 1.5 pk printf("tag VT_PROCFS, pid %d, uid %d, gid %d, mode %x, flags %x\n",
296 1.5 pk pfsp->pfs_pid,
297 1.5 pk pfsp->pfs_uid, pfsp->pfs_gid,
298 1.5 pk pfsp->pfs_mode, pfsp->pfs_flags);
299 1.5 pk
300 1.1 pk return;
301 1.1 pk }
302 1.1 pk
303 1.1 pk /*
304 1.1 pk * /proc bad operation
305 1.1 pk */
306 1.1 pk int
307 1.1 pk pfs_badop()
308 1.1 pk {
309 1.1 pk printf("pfs_badop called\n");
310 1.1 pk return EIO;
311 1.1 pk }
312 1.1 pk
313 1.1 pk #if 0 /* Moved to pfs_subr.c */
314 1.1 pk /*
315 1.1 pk * Vnode op for reading/writing.
316 1.1 pk */
317 1.1 pk /* ARGSUSED */
318 1.1 pk int
319 1.1 pk pfs_doio(vp, uio, ioflag, cred)
320 1.1 pk struct vnode *vp;
321 1.1 pk register struct uio *uio;
322 1.1 pk int ioflag;
323 1.1 pk struct ucred *cred;
324 1.1 pk {
325 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
326 1.1 pk struct proc *procp;
327 1.1 pk int error = 0;
328 1.1 pk long n, off;
329 1.1 pk caddr_t kva;
330 1.1 pk
331 1.1 pk #ifdef DEBUG
332 1.1 pk if (pfs_debug)
333 1.1 pk printf("pfs_doio(%s): vp 0x%x, proc %x\n",
334 1.1 pk uio->uio_rw==UIO_READ?"R":"W", vp, uio->uio_procp);
335 1.1 pk #endif
336 1.1 pk
337 1.1 pk #ifdef DIAGNOSTIC
338 1.1 pk if (vp->v_type != VPROC)
339 1.1 pk panic("pfs_doio vtype");
340 1.1 pk #endif
341 1.1 pk procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
342 1.1 pk if (!procp)
343 1.1 pk return ESRCH;
344 1.1 pk
345 1.1 pk if (uio->uio_resid == 0)
346 1.1 pk return (0);
347 1.1 pk if (uio->uio_offset < 0)
348 1.1 pk return (EINVAL);
349 1.1 pk
350 1.1 pk do { /* One page at a time */
351 1.1 pk off = uio->uio_offset - trunc_page(uio->uio_offset);
352 1.1 pk n = MIN(PAGE_SIZE-off, uio->uio_resid);
353 1.1 pk
354 1.1 pk /* Map page into kernel space */
355 1.1 pk error = pfs_map(procp, &kva, uio->uio_rw, uio->uio_offset);
356 1.1 pk if (error)
357 1.1 pk return error;
358 1.1 pk
359 1.1 pk error = uiomove(kva + off, (int)n, uio);
360 1.1 pk pfs_unmap(procp, kva);
361 1.1 pk
362 1.1 pk } while (error == 0 && uio->uio_resid > 0);
363 1.1 pk
364 1.1 pk return (error);
365 1.1 pk }
366 1.1 pk #endif
367 1.1 pk
368 1.1 pk /*
369 1.1 pk * Make up some attributes for a process file
370 1.1 pk */
371 1.1 pk int
372 1.1 pk pfs_getattr (vp, vap, cred, p)
373 1.1 pk struct vnode *vp;
374 1.1 pk struct vattr *vap;
375 1.1 pk struct ucred *cred;
376 1.1 pk struct proc *p;
377 1.1 pk {
378 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
379 1.1 pk struct proc *procp;
380 1.1 pk
381 1.1 pk VATTR_NULL(vap);
382 1.1 pk vap->va_type = vp->v_type;
383 1.5 pk vap->va_mode = pfsp->pfs_mode;
384 1.5 pk vap->va_flags = pfsp->pfs_vflags;
385 1.1 pk
386 1.1 pk if (vp->v_flag & VROOT) {
387 1.1 pk vap->va_nlink = 2;
388 1.1 pk vap->va_size =
389 1.1 pk roundup((2+nprocs)*sizeof(struct pfsdent), DIRBLKSIZ);
390 1.1 pk vap->va_size_rsv = 0;
391 1.5 pk vap->va_uid = pfsp->pfs_uid;
392 1.5 pk vap->va_gid = pfsp->pfs_gid;
393 1.1 pk vap->va_atime = vap->va_mtime = vap->va_ctime = time; /*XXX*/
394 1.1 pk return 0;
395 1.1 pk }
396 1.1 pk
397 1.1 pk procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
398 1.1 pk if (!procp)
399 1.1 pk return ESRCH;
400 1.1 pk
401 1.1 pk vap->va_nlink = 1;
402 1.1 pk vap->va_size = ctob( procp->p_vmspace->vm_tsize +
403 1.1 pk procp->p_vmspace->vm_dsize +
404 1.1 pk procp->p_vmspace->vm_ssize);
405 1.1 pk vap->va_size_rsv = 0;
406 1.1 pk vap->va_blocksize = page_size;
407 1.1 pk vap->va_uid = procp->p_ucred->cr_uid;
408 1.1 pk vap->va_gid = procp->p_ucred->cr_gid;
409 1.1 pk if (vap->va_uid != procp->p_cred->p_ruid)
410 1.1 pk vap->va_mode |= VSUID;
411 1.1 pk if (vap->va_gid != procp->p_cred->p_rgid)
412 1.1 pk vap->va_mode |= VSGID;
413 1.1 pk if (procp->p_flag & SLOAD) {
414 1.1 pk vap->va_atime = vap->va_mtime = vap->va_ctime =
415 1.1 pk procp->p_stats->p_start;
416 1.1 pk }
417 1.1 pk
418 1.1 pk return 0;
419 1.1 pk }
420 1.1 pk
421 1.5 pk /*
422 1.5 pk * Set some attributes for a process file
423 1.5 pk */
424 1.5 pk int
425 1.5 pk pfs_setattr (vp, vap, cred, p)
426 1.5 pk struct vnode *vp;
427 1.5 pk struct vattr *vap;
428 1.5 pk struct ucred *cred;
429 1.5 pk struct proc *p;
430 1.5 pk {
431 1.5 pk struct pfsnode *pfsp = VTOPFS(vp);
432 1.5 pk struct proc *procp;
433 1.5 pk int error = 0;
434 1.5 pk
435 1.5 pk procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
436 1.5 pk if (!procp)
437 1.5 pk return ESRCH;
438 1.5 pk
439 1.5 pk /*
440 1.5 pk * Check for unsetable attributes.
441 1.5 pk */
442 1.5 pk if ((vap->va_type != VNON) || (vap->va_nlink != (short)VNOVAL) ||
443 1.5 pk (vap->va_fsid != (long)VNOVAL) ||
444 1.5 pk (vap->va_fileid != (long)VNOVAL) ||
445 1.5 pk (vap->va_blocksize != (long)VNOVAL) ||
446 1.5 pk (vap->va_rdev != (dev_t)VNOVAL) ||
447 1.5 pk ((int)vap->va_bytes != (u_long)VNOVAL) ||
448 1.5 pk ((int)vap->va_bytes_rsv != (u_long)VNOVAL) ||
449 1.5 pk ((int)vap->va_size != (u_long)VNOVAL) ||
450 1.5 pk ((int)vap->va_size_rsv != (u_long)VNOVAL) ||
451 1.5 pk (vap->va_gen != (long)VNOVAL) ||
452 1.5 pk ((int)vap->va_atime.tv_sec != (u_long)VNOVAL) ||
453 1.5 pk ((int)vap->va_mtime.tv_sec != (u_long)VNOVAL) ||
454 1.5 pk ((int)vap->va_ctime.tv_sec != (u_long)VNOVAL) ||
455 1.5 pk (( (vap->va_uid != (uid_t)VNOVAL) ||
456 1.5 pk (vap->va_gid != (gid_t)VNOVAL)) && !(vp->v_flag & VROOT)) ) {
457 1.5 pk return (EINVAL);
458 1.5 pk }
459 1.5 pk
460 1.5 pk /* set mode bits, only rwx bits are modified */
461 1.5 pk if (vap->va_mode != (u_short)VNOVAL) {
462 1.5 pk if (cred->cr_uid != pfsp->pfs_uid &&
463 1.5 pk (error = suser(cred, &p->p_acflag)))
464 1.5 pk return (error);
465 1.5 pk pfsp->pfs_mode = vap->va_mode & 0777;
466 1.5 pk }
467 1.5 pk
468 1.5 pk /* For now, only allow to change ownership of "/proc" itself */
469 1.5 pk if ((vp->v_flag & VROOT) && vap->va_uid != (uid_t)VNOVAL) {
470 1.5 pk if ((error = suser(cred, &p->p_acflag)))
471 1.5 pk return (error);
472 1.5 pk pfsp->pfs_uid = vap->va_uid;
473 1.5 pk }
474 1.5 pk
475 1.5 pk if ((vp->v_flag & VROOT) && vap->va_gid != (gid_t)VNOVAL) {
476 1.5 pk if ((cred->cr_uid != pfsp->pfs_uid ||
477 1.5 pk !groupmember(vap->va_gid, cred)) &&
478 1.5 pk (error = suser(cred, &p->p_acflag)))
479 1.5 pk return error;
480 1.5 pk
481 1.5 pk pfsp->pfs_gid = vap->va_gid;
482 1.5 pk }
483 1.5 pk
484 1.5 pk /* chflags() */
485 1.5 pk if (vap->va_flags != (u_long)VNOVAL) {
486 1.5 pk if (cred->cr_uid != pfsp->pfs_uid &&
487 1.5 pk (error = suser(cred, &p->p_acflag)))
488 1.5 pk return (error);
489 1.5 pk if (cred->cr_uid == 0) {
490 1.5 pk pfsp->pfs_vflags = vap->va_flags;
491 1.5 pk } else {
492 1.5 pk pfsp->pfs_vflags &= 0xffff0000;
493 1.5 pk pfsp->pfs_vflags |= (vap->va_flags & 0xffff);
494 1.5 pk }
495 1.5 pk }
496 1.5 pk return 0;
497 1.5 pk }
498 1.5 pk
499 1.1 pk int
500 1.1 pk pfs_access (vp, mode, cred, p)
501 1.1 pk struct vnode *vp;
502 1.1 pk int mode;
503 1.1 pk struct ucred *cred;
504 1.1 pk struct proc *p;
505 1.1 pk {
506 1.1 pk register struct vattr *vap;
507 1.1 pk register gid_t *gp;
508 1.1 pk struct vattr vattr;
509 1.1 pk register int i;
510 1.1 pk int error;
511 1.1 pk
512 1.1 pk /*
513 1.1 pk * If you're the super-user,
514 1.1 pk * you always get access.
515 1.1 pk */
516 1.5 pk if (cred->cr_uid == (uid_t)0)
517 1.1 pk return (0);
518 1.1 pk vap = &vattr;
519 1.1 pk if (error = pfs_getattr(vp, vap, cred, p))
520 1.1 pk return (error);
521 1.1 pk /*
522 1.1 pk * Access check is based on only one of owner, group, public.
523 1.1 pk * If not owner, then check group. If not a member of the
524 1.1 pk * group, then check public access.
525 1.1 pk */
526 1.1 pk if (cred->cr_uid != vap->va_uid) {
527 1.1 pk mode >>= 3;
528 1.1 pk gp = cred->cr_groups;
529 1.1 pk for (i = 0; i < cred->cr_ngroups; i++, gp++)
530 1.1 pk if (vap->va_gid == *gp)
531 1.1 pk goto found;
532 1.1 pk mode >>= 3;
533 1.1 pk found:
534 1.1 pk ;
535 1.1 pk }
536 1.1 pk if ((vap->va_mode & mode) != 0)
537 1.1 pk return (0);
538 1.1 pk return (EACCES);
539 1.1 pk }
540 1.1 pk
541 1.1 pk /*
542 1.1 pk * /proc lookup
543 1.1 pk */
544 1.1 pk int
545 1.1 pk pfs_lookup(vp, ndp, p)
546 1.1 pk register struct vnode *vp;
547 1.1 pk register struct nameidata *ndp;
548 1.1 pk struct proc *p;
549 1.1 pk {
550 1.1 pk int lockparent, wantparent, flag, error = 0;
551 1.1 pk pid_t pid;
552 1.1 pk struct vnode *nvp;
553 1.1 pk struct pfsnode *pfsp;
554 1.1 pk struct proc *procp;
555 1.1 pk
556 1.1 pk #ifdef DEBUG
557 1.1 pk if (pfs_debug)
558 1.1 pk printf("pfs_lookup: vp 0x%x name %s proc %d\n",
559 1.1 pk vp, ndp->ni_ptr, p->p_pid);
560 1.1 pk #endif
561 1.1 pk
562 1.1 pk ndp->ni_dvp = vp;
563 1.1 pk ndp->ni_vp = NULL;
564 1.1 pk if (vp->v_type != VDIR)
565 1.1 pk return (ENOTDIR);
566 1.1 pk
567 1.1 pk lockparent = ndp->ni_nameiop & LOCKPARENT;
568 1.1 pk flag = ndp->ni_nameiop & OPMASK;
569 1.1 pk wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
570 1.1 pk if (flag != LOOKUP)
571 1.1 pk return EACCES;
572 1.1 pk if (ndp->ni_isdotdot) {
573 1.1 pk /* Should not happen */
574 1.1 pk printf("pfs_lookup: vp 0x%x: dotdot\n", vp);
575 1.1 pk return EIO;
576 1.1 pk }
577 1.1 pk if (ndp->ni_namelen == 1 && *ndp->ni_ptr == '.') {
578 1.1 pk VREF(vp);
579 1.1 pk ndp->ni_vp = vp;
580 1.1 pk return 0;
581 1.1 pk }
582 1.1 pk
583 1.1 pk pid = (pid_t)atoi(ndp->ni_ptr, ndp->ni_namelen);
584 1.1 pk if (pid == (pid_t)-1)
585 1.1 pk return ENOENT;
586 1.1 pk
587 1.1 pk if ((procp = pid?pfind(pid):&proc0) == NULL)
588 1.1 pk return ENOENT;
589 1.1 pk
590 1.5 pk /* Search pfs node list first */
591 1.1 pk for (pfsp = pfshead; pfsp != NULL; pfsp = pfsp->pfs_next) {
592 1.1 pk if (pfsp->pfs_pid == pid)
593 1.1 pk break;
594 1.1 pk }
595 1.1 pk
596 1.1 pk if (pfsp == NULL) {
597 1.1 pk struct pfsnode **pp;
598 1.1 pk error = getnewvnode(VT_PROCFS, vp->v_mount, &pfs_vnodeops, &nvp);
599 1.1 pk if (error)
600 1.1 pk return error;
601 1.1 pk
602 1.1 pk nvp->v_type = VPROC;
603 1.1 pk pfsp = VTOPFS(nvp);
604 1.5 pk pfsp->pfs_next = NULL;
605 1.1 pk pfsp->pfs_pid = pid;
606 1.1 pk pfsp->pfs_vnode = nvp;
607 1.4 pk pfsp->pfs_flags = 0;
608 1.5 pk pfsp->pfs_vflags = 0;
609 1.5 pk pfsp->pfs_uid = procp->p_ucred->cr_uid;
610 1.5 pk pfsp->pfs_gid = procp->p_ucred->cr_gid;
611 1.5 pk pfsp->pfs_mode = 0700; /* Initial access bits */
612 1.5 pk
613 1.5 pk /* Append to pfs node list */
614 1.1 pk for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next);
615 1.1 pk *pp = pfsp;
616 1.1 pk
617 1.1 pk }
618 1.1 pk ndp->ni_vp = pfsp->pfs_vnode;
619 1.1 pk
620 1.1 pk return (error);
621 1.1 pk }
622 1.1 pk
623 1.1 pk int
624 1.6 ws pfs_readdir(vp, uio, cred, eofflagp, cookies, ncookies)
625 1.1 pk struct vnode *vp;
626 1.1 pk register struct uio *uio;
627 1.1 pk struct ucred *cred;
628 1.1 pk int *eofflagp;
629 1.6 ws u_int *cookies;
630 1.6 ws int ncookies;
631 1.1 pk {
632 1.1 pk int error = 0;
633 1.1 pk int count, lost, pcnt, skipcnt, doingzomb = 0;
634 1.1 pk struct proc *p;
635 1.1 pk struct pfsdent dent;
636 1.1 pk
637 1.1 pk #ifdef DEBUG
638 1.1 pk if (pfs_debug)
639 1.1 pk printf("pfs_readdir: vp 0x%x proc %d\n",
640 1.1 pk vp, uio->uio_procp->p_pid);
641 1.1 pk #endif
642 1.1 pk count = uio->uio_resid;
643 1.1 pk count &= ~(DIRBLKSIZ - 1);
644 1.1 pk lost = uio->uio_resid - count;
645 1.1 pk if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
646 1.1 pk return (EINVAL);
647 1.1 pk uio->uio_resid = count;
648 1.1 pk uio->uio_iov->iov_len = count;
649 1.1 pk *eofflagp = 1;
650 1.1 pk skipcnt = uio->uio_offset / sizeof(struct pfsdent);
651 1.1 pk
652 1.1 pk count = 0;
653 1.1 pk if (skipcnt == 0) {
654 1.1 pk /* Fake "." and ".." entries? */
655 1.1 pk #if 1
656 1.1 pk dent.d_fileno = 2; /* XXX - Filesystem root */
657 1.1 pk dent.d_reclen = sizeof(struct pfsdent);
658 1.1 pk
659 1.1 pk dent.d_namlen = 1;
660 1.1 pk dent.d_nam[0] = '.';
661 1.1 pk dent.d_nam[1] = '\0';
662 1.1 pk error = uiomove((char *)&dent, sizeof(struct pfsdent) , uio);
663 1.1 pk if (error)
664 1.1 pk return error;
665 1.6 ws if (cookies) {
666 1.6 ws *cookies++ = sizeof(struct pfsdent);
667 1.6 ws ncookies--;
668 1.6 ws }
669 1.6 ws
670 1.1 pk dent.d_fileno = 2;
671 1.1 pk dent.d_namlen = 2;
672 1.1 pk dent.d_nam[1] = '.';
673 1.1 pk dent.d_nam[2] = '\0';
674 1.1 pk error = uiomove((char *)&dent, sizeof(struct pfsdent) , uio);
675 1.1 pk if (error)
676 1.1 pk return error;
677 1.6 ws if (cookies) {
678 1.6 ws *cookies++ = 2 * sizeof(struct pfsdent);
679 1.6 ws ncookies--;
680 1.6 ws }
681 1.1 pk #endif
682 1.1 pk count += 2*dent.d_reclen;
683 1.1 pk }
684 1.1 pk
685 1.6.2.1 mycroft p = (struct proc *)allproc;
686 1.6 ws for (pcnt = 0; p && uio->uio_resid && (!cookies || ncookies > 0); pcnt++) {
687 1.1 pk if (pcnt < skipcnt) {
688 1.1 pk p = p->p_nxt;
689 1.1 pk if (p == NULL && doingzomb == 0) {
690 1.1 pk doingzomb = 1;
691 1.1 pk p = zombproc;
692 1.1 pk }
693 1.1 pk continue;
694 1.1 pk }
695 1.1 pk *eofflagp = 0;
696 1.1 pk
697 1.1 pk /* "inode" is process slot (actually position on list) */
698 1.1 pk dent.d_fileno = (unsigned long)(pcnt+1);
699 1.1 pk dent.d_namlen = itos((unsigned int)p->p_pid, dent.d_nam);
700 1.1 pk dent.d_nam[dent.d_namlen] = '\0';
701 1.1 pk
702 1.1 pk p = p->p_nxt;
703 1.1 pk if (p == NULL && doingzomb == 0) {
704 1.1 pk doingzomb = 1;
705 1.1 pk p = zombproc;
706 1.1 pk }
707 1.1 pk if (p == NULL) {
708 1.1 pk /* Extend 'reclen' to end of block */;
709 1.1 pk dent.d_reclen = DIRBLKSIZ - (count & (DIRBLKSIZ - 1));
710 1.1 pk } else
711 1.1 pk dent.d_reclen = sizeof(struct pfsdent);
712 1.1 pk count += dent.d_reclen;
713 1.1 pk error = uiomove((char *)&dent, dent.d_reclen, uio);
714 1.1 pk if (error)
715 1.1 pk break;
716 1.6 ws if (cookies) {
717 1.6 ws *cookies++ = count;
718 1.6 ws ncookies--;
719 1.6 ws }
720 1.1 pk }
721 1.1 pk if (count == 0)
722 1.1 pk *eofflagp = 1;
723 1.1 pk
724 1.1 pk uio->uio_resid += lost;
725 1.1 pk return error;
726 1.1 pk }
727 1.1 pk
728 1.1 pk /*
729 1.1 pk * convert n to decimal representation in character array b
730 1.1 pk * return number of decimal digits produced.
731 1.1 pk */
732 1.1 pk int
733 1.1 pk itos(n, b)
734 1.1 pk unsigned int n;
735 1.1 pk char *b;
736 1.1 pk {
737 1.1 pk #define BASE 10
738 1.1 pk int m = (n<BASE)?0:itos(n/BASE, b);
739 1.1 pk
740 1.1 pk *(b+m) = "0123456789abcdef"[n%BASE];
741 1.1 pk return m+1;
742 1.1 pk }
743 1.1 pk
744 1.1 pk /*
745 1.1 pk * convert decimal ascii representation in b of length len to integer
746 1.1 pk */
747 1.1 pk int
748 1.1 pk atoi(b, len)
749 1.1 pk char *b;
750 1.1 pk unsigned int len;
751 1.1 pk {
752 1.1 pk int n = 0;
753 1.1 pk
754 1.1 pk while (len--) {
755 1.1 pk register char c = *b++;
756 1.1 pk if (c < '0' || c > '9')
757 1.1 pk return -1;
758 1.1 pk n = 10 * n + (c - '0');
759 1.1 pk }
760 1.1 pk return n;
761 1.1 pk }
762