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