procfs_vnops.c revision 1.6.2.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.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.2 mycroft * $Id: procfs_vnops.c,v 1.6.2.2 1993/11/14 22:35:07 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.6.2.2 mycroft #include <sys/param.h>
38 1.6.2.2 mycroft #include <sys/systm.h>
39 1.6.2.2 mycroft #include <sys/time.h>
40 1.6.2.2 mycroft #include <sys/kernel.h>
41 1.6.2.2 mycroft #include <sys/ioctl.h>
42 1.6.2.2 mycroft #include <sys/file.h>
43 1.6.2.2 mycroft #include <sys/proc.h>
44 1.6.2.2 mycroft #include <sys/buf.h>
45 1.6.2.2 mycroft #include <sys/vnode.h>
46 1.6.2.2 mycroft #include <sys/namei.h>
47 1.6.2.2 mycroft #include <sys/resourcevar.h>
48 1.1 pk
49 1.6.2.2 mycroft #include <vm/vm.h>
50 1.1 pk
51 1.6.2.2 mycroft #include <sys/kinfo.h>
52 1.6.2.2 mycroft #include <sys/kinfo_proc.h>
53 1.6.2.2 mycroft
54 1.6.2.2 mycroft #include <miscfs/procfs/procfs.h>
55 1.6.2.2 mycroft #include <miscfs/procfs/pfsnode.h>
56 1.6.2.2 mycroft
57 1.6.2.2 mycroft #include <machine/vmparam.h>
58 1.1 pk
59 1.1 pk /*
60 1.1 pk * procfs vnode operations.
61 1.1 pk */
62 1.1 pk struct vnodeops pfs_vnodeops = {
63 1.1 pk pfs_lookup, /* lookup */
64 1.1 pk pfs_create, /* create */
65 1.1 pk pfs_mknod, /* mknod */
66 1.1 pk pfs_open, /* open */
67 1.1 pk pfs_close, /* close */
68 1.1 pk pfs_access, /* access */
69 1.1 pk pfs_getattr, /* getattr */
70 1.1 pk pfs_setattr, /* setattr */
71 1.1 pk pfs_read, /* read */
72 1.1 pk pfs_write, /* write */
73 1.1 pk pfs_ioctl, /* ioctl */
74 1.1 pk pfs_select, /* select */
75 1.1 pk pfs_mmap, /* mmap */
76 1.1 pk pfs_fsync, /* fsync */
77 1.1 pk pfs_seek, /* seek */
78 1.1 pk pfs_remove, /* remove */
79 1.1 pk pfs_link, /* link */
80 1.1 pk pfs_rename, /* rename */
81 1.1 pk pfs_mkdir, /* mkdir */
82 1.1 pk pfs_rmdir, /* rmdir */
83 1.1 pk pfs_symlink, /* symlink */
84 1.1 pk pfs_readdir, /* readdir */
85 1.1 pk pfs_readlink, /* readlink */
86 1.1 pk pfs_abortop, /* abortop */
87 1.1 pk pfs_inactive, /* inactive */
88 1.1 pk pfs_reclaim, /* reclaim */
89 1.1 pk pfs_lock, /* lock */
90 1.1 pk pfs_unlock, /* unlock */
91 1.1 pk pfs_bmap, /* bmap */
92 1.1 pk pfs_strategy, /* strategy */
93 1.1 pk pfs_print, /* print */
94 1.1 pk pfs_islocked, /* islocked */
95 1.1 pk pfs_advlock, /* advlock */
96 1.1 pk };
97 1.1 pk
98 1.1 pk /*
99 1.1 pk * Vnode Operations.
100 1.1 pk *
101 1.1 pk */
102 1.1 pk /* ARGSUSED */
103 1.1 pk int
104 1.1 pk pfs_open(vp, mode, cred, p)
105 1.1 pk register struct vnode *vp;
106 1.1 pk int mode;
107 1.1 pk struct ucred *cred;
108 1.1 pk struct proc *p;
109 1.1 pk {
110 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
111 1.1 pk
112 1.1 pk #ifdef DEBUG
113 1.1 pk if (pfs_debug)
114 1.1 pk printf("pfs_open: vp 0x%x, proc %d\n", vp, p->p_pid);
115 1.1 pk #endif
116 1.1 pk
117 1.1 pk if ((pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0) == NULL)
118 1.1 pk return ESRCH;
119 1.1 pk
120 1.4 pk if ( (pfsp->pfs_flags & FWRITE) && (mode & O_EXCL) ||
121 1.4 pk (pfsp->pfs_flags & O_EXCL) && (mode & FWRITE) )
122 1.1 pk return EBUSY;
123 1.1 pk
124 1.1 pk
125 1.1 pk if (mode & FWRITE)
126 1.4 pk pfsp->pfs_flags = (mode & (FWRITE|O_EXCL));
127 1.1 pk return 0;
128 1.1 pk }
129 1.1 pk
130 1.1 pk /*
131 1.1 pk * /proc filesystem close routine
132 1.1 pk */
133 1.1 pk /* ARGSUSED */
134 1.1 pk int
135 1.1 pk pfs_close(vp, flag, cred, p)
136 1.1 pk register struct vnode *vp;
137 1.1 pk int flag;
138 1.1 pk struct ucred *cred;
139 1.1 pk struct proc *p;
140 1.1 pk {
141 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
142 1.1 pk
143 1.1 pk #ifdef DEBUG
144 1.1 pk if (pfs_debug)
145 1.1 pk printf("pfs_close: vp 0x%x proc %d\n", vp, p->p_pid);
146 1.1 pk #endif
147 1.4 pk if ((flag & FWRITE) && (pfsp->pfs_flags & O_EXCL))
148 1.4 pk pfsp->pfs_flags &= ~(FWRITE|O_EXCL);
149 1.1 pk
150 1.1 pk return (0);
151 1.1 pk }
152 1.1 pk
153 1.1 pk /*
154 1.1 pk * Ioctl operation.
155 1.1 pk */
156 1.1 pk /* ARGSUSED */
157 1.1 pk int
158 1.1 pk pfs_ioctl(vp, com, data, fflag, cred, p)
159 1.1 pk struct vnode *vp;
160 1.1 pk int com;
161 1.1 pk caddr_t data;
162 1.1 pk int fflag;
163 1.1 pk struct ucred *cred;
164 1.1 pk struct proc *p;
165 1.1 pk {
166 1.1 pk int error = 0;
167 1.1 pk struct proc *procp;
168 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
169 1.1 pk
170 1.1 pk procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
171 1.1 pk if (!procp)
172 1.1 pk return ESRCH;
173 1.1 pk
174 1.1 pk switch (com) {
175 1.1 pk
176 1.1 pk case PIOCGPINFO: {
177 1.1 pk int copysize = sizeof(struct kinfo_proc), needed;
178 1.1 pk kinfo_doproc(KINFO_PROC_PID, data, ©size,
179 1.1 pk pfsp->pfs_pid, &needed);
180 1.1 pk break;
181 1.1 pk }
182 1.1 pk
183 1.1 pk #ifdef notyet /* Changes to proc.h needed */
184 1.1 pk case PIOCGSIGSET:
185 1.1 pk procp->p_psigset = *(sigset_t *)data;
186 1.1 pk break;
187 1.1 pk
188 1.1 pk case PIOCSSIGSET:
189 1.1 pk *(sigset_t *)data = procp->p_psigset;
190 1.1 pk break;
191 1.1 pk
192 1.1 pk case PIOCGFLTSET:
193 1.1 pk procp->p_pfltset = *(sigflt_t *)data;
194 1.1 pk break;
195 1.1 pk
196 1.1 pk case PIOCSFLTSET:
197 1.1 pk *(fltset_t *)data = procp->p_pfltset;
198 1.1 pk break;
199 1.1 pk #endif
200 1.1 pk
201 1.1 pk case PIOCGMAPFD:
202 1.1 pk error = pfs_vmfd(procp, pfsp, (struct vmfd *)data, p);
203 1.1 pk break;
204 1.1 pk
205 1.1 pk case PIOCGNMAP:
206 1.1 pk *(int *)data = pfs_vm_nentries(procp, pfsp);
207 1.1 pk break;
208 1.1 pk
209 1.1 pk case PIOCGMAP:
210 1.1 pk error = pfs_vmmap(procp, pfsp, *(struct procmap *)data);
211 1.1 pk break;
212 1.1 pk
213 1.1 pk default:
214 1.1 pk error = EIO;
215 1.1 pk break;
216 1.1 pk }
217 1.1 pk return error;
218 1.1 pk }
219 1.1 pk
220 1.1 pk /*
221 1.1 pk * Pass I/O requests to the memory filesystem process.
222 1.1 pk */
223 1.1 pk int
224 1.1 pk pfs_strategy(bp)
225 1.1 pk register struct buf *bp;
226 1.1 pk {
227 1.1 pk struct vnode *vp;
228 1.1 pk struct proc *p = curproc; /* XXX */
229 1.1 pk
230 1.1 pk return (0);
231 1.1 pk }
232 1.1 pk
233 1.1 pk /*
234 1.1 pk * This is a noop, simply returning what one has been given.
235 1.1 pk */
236 1.1 pk int
237 1.1 pk pfs_bmap(vp, bn, vpp, bnp)
238 1.1 pk struct vnode *vp;
239 1.1 pk daddr_t bn;
240 1.1 pk struct vnode **vpp;
241 1.1 pk daddr_t *bnp;
242 1.1 pk {
243 1.1 pk
244 1.1 pk if (vpp != NULL)
245 1.1 pk *vpp = vp;
246 1.1 pk if (bnp != NULL)
247 1.1 pk *bnp = bn;
248 1.1 pk return (0);
249 1.1 pk }
250 1.1 pk
251 1.1 pk /*
252 1.1 pk * /proc filesystem inactive routine
253 1.1 pk */
254 1.1 pk /* ARGSUSED */
255 1.1 pk int
256 1.1 pk pfs_inactive(vp, p)
257 1.1 pk struct vnode *vp;
258 1.1 pk struct proc *p;
259 1.1 pk {
260 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
261 1.1 pk
262 1.5 pk if ((pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0) == NULL
263 1.5 pk && vp->v_usecount == 0)
264 1.1 pk vgone(vp);
265 1.5 pk
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.5 pk struct pfsnode *pfsp = VTOPFS(vp);
296 1.5 pk
297 1.5 pk printf("tag VT_PROCFS, pid %d, uid %d, gid %d, mode %x, flags %x\n",
298 1.5 pk pfsp->pfs_pid,
299 1.5 pk pfsp->pfs_uid, pfsp->pfs_gid,
300 1.5 pk pfsp->pfs_mode, pfsp->pfs_flags);
301 1.5 pk
302 1.1 pk return;
303 1.1 pk }
304 1.1 pk
305 1.1 pk /*
306 1.1 pk * /proc bad operation
307 1.1 pk */
308 1.1 pk int
309 1.1 pk pfs_badop()
310 1.1 pk {
311 1.1 pk printf("pfs_badop called\n");
312 1.1 pk return EIO;
313 1.1 pk }
314 1.1 pk
315 1.1 pk #if 0 /* Moved to pfs_subr.c */
316 1.1 pk /*
317 1.1 pk * Vnode op for reading/writing.
318 1.1 pk */
319 1.1 pk /* ARGSUSED */
320 1.1 pk int
321 1.1 pk pfs_doio(vp, uio, ioflag, cred)
322 1.1 pk struct vnode *vp;
323 1.1 pk register struct uio *uio;
324 1.1 pk int ioflag;
325 1.1 pk struct ucred *cred;
326 1.1 pk {
327 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
328 1.1 pk struct proc *procp;
329 1.1 pk int error = 0;
330 1.1 pk long n, off;
331 1.1 pk caddr_t kva;
332 1.1 pk
333 1.1 pk #ifdef DEBUG
334 1.1 pk if (pfs_debug)
335 1.1 pk printf("pfs_doio(%s): vp 0x%x, proc %x\n",
336 1.1 pk uio->uio_rw==UIO_READ?"R":"W", vp, uio->uio_procp);
337 1.1 pk #endif
338 1.1 pk
339 1.1 pk #ifdef DIAGNOSTIC
340 1.1 pk if (vp->v_type != VPROC)
341 1.1 pk panic("pfs_doio vtype");
342 1.1 pk #endif
343 1.1 pk procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
344 1.1 pk if (!procp)
345 1.1 pk return ESRCH;
346 1.1 pk
347 1.1 pk if (uio->uio_resid == 0)
348 1.1 pk return (0);
349 1.1 pk if (uio->uio_offset < 0)
350 1.1 pk return (EINVAL);
351 1.1 pk
352 1.1 pk do { /* One page at a time */
353 1.1 pk off = uio->uio_offset - trunc_page(uio->uio_offset);
354 1.1 pk n = MIN(PAGE_SIZE-off, uio->uio_resid);
355 1.1 pk
356 1.1 pk /* Map page into kernel space */
357 1.1 pk error = pfs_map(procp, &kva, uio->uio_rw, uio->uio_offset);
358 1.1 pk if (error)
359 1.1 pk return error;
360 1.1 pk
361 1.1 pk error = uiomove(kva + off, (int)n, uio);
362 1.1 pk pfs_unmap(procp, kva);
363 1.1 pk
364 1.1 pk } while (error == 0 && uio->uio_resid > 0);
365 1.1 pk
366 1.1 pk return (error);
367 1.1 pk }
368 1.1 pk #endif
369 1.1 pk
370 1.1 pk /*
371 1.1 pk * Make up some attributes for a process file
372 1.1 pk */
373 1.1 pk int
374 1.1 pk pfs_getattr (vp, vap, cred, p)
375 1.1 pk struct vnode *vp;
376 1.1 pk struct vattr *vap;
377 1.1 pk struct ucred *cred;
378 1.1 pk struct proc *p;
379 1.1 pk {
380 1.1 pk struct pfsnode *pfsp = VTOPFS(vp);
381 1.1 pk struct proc *procp;
382 1.1 pk
383 1.1 pk VATTR_NULL(vap);
384 1.1 pk vap->va_type = vp->v_type;
385 1.5 pk vap->va_mode = pfsp->pfs_mode;
386 1.5 pk vap->va_flags = pfsp->pfs_vflags;
387 1.1 pk
388 1.1 pk if (vp->v_flag & VROOT) {
389 1.1 pk vap->va_nlink = 2;
390 1.1 pk vap->va_size =
391 1.1 pk roundup((2+nprocs)*sizeof(struct pfsdent), DIRBLKSIZ);
392 1.1 pk vap->va_size_rsv = 0;
393 1.5 pk vap->va_uid = pfsp->pfs_uid;
394 1.5 pk vap->va_gid = pfsp->pfs_gid;
395 1.1 pk vap->va_atime = vap->va_mtime = vap->va_ctime = time; /*XXX*/
396 1.1 pk return 0;
397 1.1 pk }
398 1.1 pk
399 1.1 pk procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
400 1.1 pk if (!procp)
401 1.1 pk return ESRCH;
402 1.1 pk
403 1.1 pk vap->va_nlink = 1;
404 1.1 pk vap->va_size = ctob( procp->p_vmspace->vm_tsize +
405 1.1 pk procp->p_vmspace->vm_dsize +
406 1.1 pk procp->p_vmspace->vm_ssize);
407 1.1 pk vap->va_size_rsv = 0;
408 1.1 pk vap->va_blocksize = page_size;
409 1.1 pk vap->va_uid = procp->p_ucred->cr_uid;
410 1.1 pk vap->va_gid = procp->p_ucred->cr_gid;
411 1.1 pk if (vap->va_uid != procp->p_cred->p_ruid)
412 1.1 pk vap->va_mode |= VSUID;
413 1.1 pk if (vap->va_gid != procp->p_cred->p_rgid)
414 1.1 pk vap->va_mode |= VSGID;
415 1.1 pk if (procp->p_flag & SLOAD) {
416 1.1 pk vap->va_atime = vap->va_mtime = vap->va_ctime =
417 1.1 pk procp->p_stats->p_start;
418 1.1 pk }
419 1.1 pk
420 1.1 pk return 0;
421 1.1 pk }
422 1.1 pk
423 1.5 pk /*
424 1.5 pk * Set some attributes for a process file
425 1.5 pk */
426 1.5 pk int
427 1.5 pk pfs_setattr (vp, vap, cred, p)
428 1.5 pk struct vnode *vp;
429 1.5 pk struct vattr *vap;
430 1.5 pk struct ucred *cred;
431 1.5 pk struct proc *p;
432 1.5 pk {
433 1.5 pk struct pfsnode *pfsp = VTOPFS(vp);
434 1.5 pk struct proc *procp;
435 1.5 pk int error = 0;
436 1.5 pk
437 1.5 pk procp = pfsp->pfs_pid?pfind(pfsp->pfs_pid):&proc0;
438 1.5 pk if (!procp)
439 1.5 pk return ESRCH;
440 1.5 pk
441 1.5 pk /*
442 1.5 pk * Check for unsetable attributes.
443 1.5 pk */
444 1.5 pk if ((vap->va_type != VNON) || (vap->va_nlink != (short)VNOVAL) ||
445 1.5 pk (vap->va_fsid != (long)VNOVAL) ||
446 1.5 pk (vap->va_fileid != (long)VNOVAL) ||
447 1.5 pk (vap->va_blocksize != (long)VNOVAL) ||
448 1.5 pk (vap->va_rdev != (dev_t)VNOVAL) ||
449 1.5 pk ((int)vap->va_bytes != (u_long)VNOVAL) ||
450 1.5 pk ((int)vap->va_bytes_rsv != (u_long)VNOVAL) ||
451 1.5 pk ((int)vap->va_size != (u_long)VNOVAL) ||
452 1.5 pk ((int)vap->va_size_rsv != (u_long)VNOVAL) ||
453 1.5 pk (vap->va_gen != (long)VNOVAL) ||
454 1.5 pk ((int)vap->va_atime.tv_sec != (u_long)VNOVAL) ||
455 1.5 pk ((int)vap->va_mtime.tv_sec != (u_long)VNOVAL) ||
456 1.5 pk ((int)vap->va_ctime.tv_sec != (u_long)VNOVAL) ||
457 1.5 pk (( (vap->va_uid != (uid_t)VNOVAL) ||
458 1.5 pk (vap->va_gid != (gid_t)VNOVAL)) && !(vp->v_flag & VROOT)) ) {
459 1.5 pk return (EINVAL);
460 1.5 pk }
461 1.5 pk
462 1.5 pk /* set mode bits, only rwx bits are modified */
463 1.5 pk if (vap->va_mode != (u_short)VNOVAL) {
464 1.5 pk if (cred->cr_uid != pfsp->pfs_uid &&
465 1.5 pk (error = suser(cred, &p->p_acflag)))
466 1.5 pk return (error);
467 1.5 pk pfsp->pfs_mode = vap->va_mode & 0777;
468 1.5 pk }
469 1.5 pk
470 1.5 pk /* For now, only allow to change ownership of "/proc" itself */
471 1.5 pk if ((vp->v_flag & VROOT) && vap->va_uid != (uid_t)VNOVAL) {
472 1.5 pk if ((error = suser(cred, &p->p_acflag)))
473 1.5 pk return (error);
474 1.5 pk pfsp->pfs_uid = vap->va_uid;
475 1.5 pk }
476 1.5 pk
477 1.5 pk if ((vp->v_flag & VROOT) && vap->va_gid != (gid_t)VNOVAL) {
478 1.5 pk if ((cred->cr_uid != pfsp->pfs_uid ||
479 1.5 pk !groupmember(vap->va_gid, cred)) &&
480 1.5 pk (error = suser(cred, &p->p_acflag)))
481 1.5 pk return error;
482 1.5 pk
483 1.5 pk pfsp->pfs_gid = vap->va_gid;
484 1.5 pk }
485 1.5 pk
486 1.5 pk /* chflags() */
487 1.5 pk if (vap->va_flags != (u_long)VNOVAL) {
488 1.5 pk if (cred->cr_uid != pfsp->pfs_uid &&
489 1.5 pk (error = suser(cred, &p->p_acflag)))
490 1.5 pk return (error);
491 1.5 pk if (cred->cr_uid == 0) {
492 1.5 pk pfsp->pfs_vflags = vap->va_flags;
493 1.5 pk } else {
494 1.5 pk pfsp->pfs_vflags &= 0xffff0000;
495 1.5 pk pfsp->pfs_vflags |= (vap->va_flags & 0xffff);
496 1.5 pk }
497 1.5 pk }
498 1.5 pk return 0;
499 1.5 pk }
500 1.5 pk
501 1.1 pk int
502 1.1 pk pfs_access (vp, mode, cred, p)
503 1.1 pk struct vnode *vp;
504 1.1 pk int mode;
505 1.1 pk struct ucred *cred;
506 1.1 pk struct proc *p;
507 1.1 pk {
508 1.1 pk register struct vattr *vap;
509 1.1 pk register gid_t *gp;
510 1.1 pk struct vattr vattr;
511 1.1 pk register int i;
512 1.1 pk int error;
513 1.1 pk
514 1.1 pk /*
515 1.1 pk * If you're the super-user,
516 1.1 pk * you always get access.
517 1.1 pk */
518 1.5 pk if (cred->cr_uid == (uid_t)0)
519 1.1 pk return (0);
520 1.1 pk vap = &vattr;
521 1.1 pk if (error = pfs_getattr(vp, vap, cred, p))
522 1.1 pk return (error);
523 1.1 pk /*
524 1.1 pk * Access check is based on only one of owner, group, public.
525 1.1 pk * If not owner, then check group. If not a member of the
526 1.1 pk * group, then check public access.
527 1.1 pk */
528 1.1 pk if (cred->cr_uid != vap->va_uid) {
529 1.1 pk mode >>= 3;
530 1.1 pk gp = cred->cr_groups;
531 1.1 pk for (i = 0; i < cred->cr_ngroups; i++, gp++)
532 1.1 pk if (vap->va_gid == *gp)
533 1.1 pk goto found;
534 1.1 pk mode >>= 3;
535 1.1 pk found:
536 1.1 pk ;
537 1.1 pk }
538 1.1 pk if ((vap->va_mode & mode) != 0)
539 1.1 pk return (0);
540 1.1 pk return (EACCES);
541 1.1 pk }
542 1.1 pk
543 1.1 pk /*
544 1.1 pk * /proc lookup
545 1.1 pk */
546 1.1 pk int
547 1.1 pk pfs_lookup(vp, ndp, p)
548 1.1 pk register struct vnode *vp;
549 1.1 pk register struct nameidata *ndp;
550 1.1 pk struct proc *p;
551 1.1 pk {
552 1.1 pk int lockparent, wantparent, flag, error = 0;
553 1.1 pk pid_t pid;
554 1.1 pk struct vnode *nvp;
555 1.1 pk struct pfsnode *pfsp;
556 1.1 pk struct proc *procp;
557 1.1 pk
558 1.1 pk #ifdef DEBUG
559 1.1 pk if (pfs_debug)
560 1.1 pk printf("pfs_lookup: vp 0x%x name %s proc %d\n",
561 1.1 pk vp, ndp->ni_ptr, p->p_pid);
562 1.1 pk #endif
563 1.1 pk
564 1.1 pk ndp->ni_dvp = vp;
565 1.1 pk ndp->ni_vp = NULL;
566 1.1 pk if (vp->v_type != VDIR)
567 1.1 pk return (ENOTDIR);
568 1.1 pk
569 1.1 pk lockparent = ndp->ni_nameiop & LOCKPARENT;
570 1.1 pk flag = ndp->ni_nameiop & OPMASK;
571 1.1 pk wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
572 1.1 pk if (flag != LOOKUP)
573 1.1 pk return EACCES;
574 1.1 pk if (ndp->ni_isdotdot) {
575 1.1 pk /* Should not happen */
576 1.1 pk printf("pfs_lookup: vp 0x%x: dotdot\n", vp);
577 1.1 pk return EIO;
578 1.1 pk }
579 1.1 pk if (ndp->ni_namelen == 1 && *ndp->ni_ptr == '.') {
580 1.1 pk VREF(vp);
581 1.1 pk ndp->ni_vp = vp;
582 1.1 pk return 0;
583 1.1 pk }
584 1.1 pk
585 1.1 pk pid = (pid_t)atoi(ndp->ni_ptr, ndp->ni_namelen);
586 1.1 pk if (pid == (pid_t)-1)
587 1.1 pk return ENOENT;
588 1.1 pk
589 1.1 pk if ((procp = pid?pfind(pid):&proc0) == NULL)
590 1.1 pk return ENOENT;
591 1.1 pk
592 1.5 pk /* Search pfs node list first */
593 1.1 pk for (pfsp = pfshead; pfsp != NULL; pfsp = pfsp->pfs_next) {
594 1.1 pk if (pfsp->pfs_pid == pid)
595 1.1 pk break;
596 1.1 pk }
597 1.1 pk
598 1.1 pk if (pfsp == NULL) {
599 1.1 pk struct pfsnode **pp;
600 1.1 pk error = getnewvnode(VT_PROCFS, vp->v_mount, &pfs_vnodeops, &nvp);
601 1.1 pk if (error)
602 1.1 pk return error;
603 1.1 pk
604 1.1 pk nvp->v_type = VPROC;
605 1.1 pk pfsp = VTOPFS(nvp);
606 1.5 pk pfsp->pfs_next = NULL;
607 1.1 pk pfsp->pfs_pid = pid;
608 1.1 pk pfsp->pfs_vnode = nvp;
609 1.4 pk pfsp->pfs_flags = 0;
610 1.5 pk pfsp->pfs_vflags = 0;
611 1.5 pk pfsp->pfs_uid = procp->p_ucred->cr_uid;
612 1.5 pk pfsp->pfs_gid = procp->p_ucred->cr_gid;
613 1.5 pk pfsp->pfs_mode = 0700; /* Initial access bits */
614 1.5 pk
615 1.5 pk /* Append to pfs node list */
616 1.1 pk for (pp = &pfshead; *pp; pp = &(*pp)->pfs_next);
617 1.1 pk *pp = pfsp;
618 1.1 pk
619 1.1 pk }
620 1.1 pk ndp->ni_vp = pfsp->pfs_vnode;
621 1.1 pk
622 1.1 pk return (error);
623 1.1 pk }
624 1.1 pk
625 1.1 pk int
626 1.6 ws pfs_readdir(vp, uio, cred, eofflagp, cookies, ncookies)
627 1.1 pk struct vnode *vp;
628 1.1 pk register struct uio *uio;
629 1.1 pk struct ucred *cred;
630 1.1 pk int *eofflagp;
631 1.6 ws u_int *cookies;
632 1.6 ws int ncookies;
633 1.1 pk {
634 1.1 pk int error = 0;
635 1.1 pk int count, lost, pcnt, skipcnt, doingzomb = 0;
636 1.1 pk struct proc *p;
637 1.1 pk struct pfsdent dent;
638 1.1 pk
639 1.1 pk #ifdef DEBUG
640 1.1 pk if (pfs_debug)
641 1.1 pk printf("pfs_readdir: vp 0x%x proc %d\n",
642 1.1 pk vp, uio->uio_procp->p_pid);
643 1.1 pk #endif
644 1.1 pk count = uio->uio_resid;
645 1.1 pk count &= ~(DIRBLKSIZ - 1);
646 1.1 pk lost = uio->uio_resid - count;
647 1.1 pk if (count < DIRBLKSIZ || (uio->uio_offset & (DIRBLKSIZ -1)))
648 1.1 pk return (EINVAL);
649 1.1 pk uio->uio_resid = count;
650 1.1 pk uio->uio_iov->iov_len = count;
651 1.1 pk *eofflagp = 1;
652 1.1 pk skipcnt = uio->uio_offset / sizeof(struct pfsdent);
653 1.1 pk
654 1.1 pk count = 0;
655 1.1 pk if (skipcnt == 0) {
656 1.1 pk /* Fake "." and ".." entries? */
657 1.1 pk #if 1
658 1.1 pk dent.d_fileno = 2; /* XXX - Filesystem root */
659 1.1 pk dent.d_reclen = sizeof(struct pfsdent);
660 1.1 pk
661 1.1 pk dent.d_namlen = 1;
662 1.1 pk dent.d_nam[0] = '.';
663 1.1 pk dent.d_nam[1] = '\0';
664 1.1 pk error = uiomove((char *)&dent, sizeof(struct pfsdent) , uio);
665 1.1 pk if (error)
666 1.1 pk return error;
667 1.6 ws if (cookies) {
668 1.6 ws *cookies++ = sizeof(struct pfsdent);
669 1.6 ws ncookies--;
670 1.6 ws }
671 1.6 ws
672 1.1 pk dent.d_fileno = 2;
673 1.1 pk dent.d_namlen = 2;
674 1.1 pk dent.d_nam[1] = '.';
675 1.1 pk dent.d_nam[2] = '\0';
676 1.1 pk error = uiomove((char *)&dent, sizeof(struct pfsdent) , uio);
677 1.1 pk if (error)
678 1.1 pk return error;
679 1.6 ws if (cookies) {
680 1.6 ws *cookies++ = 2 * sizeof(struct pfsdent);
681 1.6 ws ncookies--;
682 1.6 ws }
683 1.1 pk #endif
684 1.1 pk count += 2*dent.d_reclen;
685 1.1 pk }
686 1.1 pk
687 1.6.2.1 mycroft p = (struct proc *)allproc;
688 1.6 ws for (pcnt = 0; p && uio->uio_resid && (!cookies || ncookies > 0); pcnt++) {
689 1.1 pk if (pcnt < skipcnt) {
690 1.1 pk p = p->p_nxt;
691 1.1 pk if (p == NULL && doingzomb == 0) {
692 1.1 pk doingzomb = 1;
693 1.1 pk p = zombproc;
694 1.1 pk }
695 1.1 pk continue;
696 1.1 pk }
697 1.1 pk *eofflagp = 0;
698 1.1 pk
699 1.1 pk /* "inode" is process slot (actually position on list) */
700 1.1 pk dent.d_fileno = (unsigned long)(pcnt+1);
701 1.1 pk dent.d_namlen = itos((unsigned int)p->p_pid, dent.d_nam);
702 1.1 pk dent.d_nam[dent.d_namlen] = '\0';
703 1.1 pk
704 1.1 pk p = p->p_nxt;
705 1.1 pk if (p == NULL && doingzomb == 0) {
706 1.1 pk doingzomb = 1;
707 1.1 pk p = zombproc;
708 1.1 pk }
709 1.1 pk if (p == NULL) {
710 1.1 pk /* Extend 'reclen' to end of block */;
711 1.1 pk dent.d_reclen = DIRBLKSIZ - (count & (DIRBLKSIZ - 1));
712 1.1 pk } else
713 1.1 pk dent.d_reclen = sizeof(struct pfsdent);
714 1.1 pk count += dent.d_reclen;
715 1.1 pk error = uiomove((char *)&dent, dent.d_reclen, uio);
716 1.1 pk if (error)
717 1.1 pk break;
718 1.6 ws if (cookies) {
719 1.6 ws *cookies++ = count;
720 1.6 ws ncookies--;
721 1.6 ws }
722 1.1 pk }
723 1.1 pk if (count == 0)
724 1.1 pk *eofflagp = 1;
725 1.1 pk
726 1.1 pk uio->uio_resid += lost;
727 1.1 pk return error;
728 1.1 pk }
729 1.1 pk
730 1.1 pk /*
731 1.1 pk * convert n to decimal representation in character array b
732 1.1 pk * return number of decimal digits produced.
733 1.1 pk */
734 1.1 pk int
735 1.1 pk itos(n, b)
736 1.1 pk unsigned int n;
737 1.1 pk char *b;
738 1.1 pk {
739 1.1 pk #define BASE 10
740 1.1 pk int m = (n<BASE)?0:itos(n/BASE, b);
741 1.1 pk
742 1.1 pk *(b+m) = "0123456789abcdef"[n%BASE];
743 1.1 pk return m+1;
744 1.1 pk }
745 1.1 pk
746 1.1 pk /*
747 1.1 pk * convert decimal ascii representation in b of length len to integer
748 1.1 pk */
749 1.1 pk int
750 1.1 pk atoi(b, len)
751 1.1 pk char *b;
752 1.1 pk unsigned int len;
753 1.1 pk {
754 1.1 pk int n = 0;
755 1.1 pk
756 1.1 pk while (len--) {
757 1.1 pk register char c = *b++;
758 1.1 pk if (c < '0' || c > '9')
759 1.1 pk return -1;
760 1.1 pk n = 10 * n + (c - '0');
761 1.1 pk }
762 1.1 pk return n;
763 1.1 pk }
764