]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libprocstat/libprocstat.c
Fix Machine Check Exception on Page Size Change.
[FreeBSD/FreeBSD.git] / lib / libprocstat / libprocstat.c
1 /*-
2  * Copyright (c) 2017 Dell EMC
3  * Copyright (c) 2009 Stanislav Sedov <stas@FreeBSD.org>
4  * Copyright (c) 1988, 1993
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *      This product includes software developed by the University of
18  *      California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include <sys/param.h>
40 #include <sys/elf.h>
41 #include <sys/time.h>
42 #include <sys/resourcevar.h>
43 #define _WANT_UCRED
44 #include <sys/ucred.h>
45 #undef _WANT_UCRED
46 #include <sys/proc.h>
47 #include <sys/user.h>
48 #include <sys/stat.h>
49 #include <sys/vnode.h>
50 #include <sys/socket.h>
51 #include <sys/socketvar.h>
52 #include <sys/domain.h>
53 #include <sys/protosw.h>
54 #include <sys/un.h>
55 #include <sys/unpcb.h>
56 #include <sys/sysctl.h>
57 #include <sys/tty.h>
58 #include <sys/filedesc.h>
59 #include <sys/queue.h>
60 #define _WANT_FILE
61 #include <sys/file.h>
62 #include <sys/conf.h>
63 #include <sys/ksem.h>
64 #include <sys/mman.h>
65 #include <sys/capsicum.h>
66 #include <sys/ptrace.h>
67 #define _KERNEL
68 #include <sys/mount.h>
69 #include <sys/pipe.h>
70 #include <ufs/ufs/quota.h>
71 #include <ufs/ufs/inode.h>
72 #include <fs/devfs/devfs.h>
73 #include <fs/devfs/devfs_int.h>
74 #undef _KERNEL
75 #include <nfs/nfsproto.h>
76 #include <nfsclient/nfs.h>
77 #include <nfsclient/nfsnode.h>
78
79 #include <vm/vm.h>
80 #include <vm/vm_map.h>
81 #include <vm/vm_object.h>
82
83 #include <net/route.h>
84 #include <netinet/in.h>
85 #include <netinet/in_systm.h>
86 #include <netinet/ip.h>
87 #include <netinet/in_pcb.h>
88
89 #include <assert.h>
90 #include <ctype.h>
91 #include <err.h>
92 #include <fcntl.h>
93 #include <kvm.h>
94 #include <libutil.h>
95 #include <limits.h>
96 #include <paths.h>
97 #include <pwd.h>
98 #include <stdio.h>
99 #include <stdlib.h>
100 #include <stddef.h>
101 #include <string.h>
102 #include <unistd.h>
103 #include <netdb.h>
104
105 #include <libprocstat.h>
106 #include "libprocstat_internal.h"
107 #include "common_kvm.h"
108 #include "core.h"
109
110 int     statfs(const char *, struct statfs *);  /* XXX */
111
112 #define PROCSTAT_KVM    1
113 #define PROCSTAT_SYSCTL 2
114 #define PROCSTAT_CORE   3
115
116 static char     **getargv(struct procstat *procstat, struct kinfo_proc *kp,
117     size_t nchr, int env);
118 static char     *getmnton(kvm_t *kd, struct mount *m);
119 static struct kinfo_vmentry *   kinfo_getvmmap_core(struct procstat_core *core,
120     int *cntp);
121 static Elf_Auxinfo      *procstat_getauxv_core(struct procstat_core *core,
122     unsigned int *cntp);
123 static Elf_Auxinfo      *procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp);
124 static struct filestat_list     *procstat_getfiles_kvm(
125     struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
126 static struct filestat_list     *procstat_getfiles_sysctl(
127     struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
128 static int      procstat_get_pipe_info_sysctl(struct filestat *fst,
129     struct pipestat *pipe, char *errbuf);
130 static int      procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst,
131     struct pipestat *pipe, char *errbuf);
132 static int      procstat_get_pts_info_sysctl(struct filestat *fst,
133     struct ptsstat *pts, char *errbuf);
134 static int      procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst,
135     struct ptsstat *pts, char *errbuf);
136 static int      procstat_get_sem_info_sysctl(struct filestat *fst,
137     struct semstat *sem, char *errbuf);
138 static int      procstat_get_sem_info_kvm(kvm_t *kd, struct filestat *fst,
139     struct semstat *sem, char *errbuf);
140 static int      procstat_get_shm_info_sysctl(struct filestat *fst,
141     struct shmstat *shm, char *errbuf);
142 static int      procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst,
143     struct shmstat *shm, char *errbuf);
144 static int      procstat_get_socket_info_sysctl(struct filestat *fst,
145     struct sockstat *sock, char *errbuf);
146 static int      procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst,
147     struct sockstat *sock, char *errbuf);
148 static int      to_filestat_flags(int flags);
149 static int      procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
150     struct vnstat *vn, char *errbuf);
151 static int      procstat_get_vnode_info_sysctl(struct filestat *fst,
152     struct vnstat *vn, char *errbuf);
153 static gid_t    *procstat_getgroups_core(struct procstat_core *core,
154     unsigned int *count);
155 static gid_t *  procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp,
156     unsigned int *count);
157 static gid_t    *procstat_getgroups_sysctl(pid_t pid, unsigned int *count);
158 static struct kinfo_kstack      *procstat_getkstack_sysctl(pid_t pid,
159     int *cntp);
160 static int      procstat_getosrel_core(struct procstat_core *core,
161     int *osrelp);
162 static int      procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp,
163     int *osrelp);
164 static int      procstat_getosrel_sysctl(pid_t pid, int *osrelp);
165 static int      procstat_getpathname_core(struct procstat_core *core,
166     char *pathname, size_t maxlen);
167 static int      procstat_getpathname_sysctl(pid_t pid, char *pathname,
168     size_t maxlen);
169 static int      procstat_getrlimit_core(struct procstat_core *core, int which,
170     struct rlimit* rlimit);
171 static int      procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp,
172     int which, struct rlimit* rlimit);
173 static int      procstat_getrlimit_sysctl(pid_t pid, int which,
174     struct rlimit* rlimit);
175 static int      procstat_getumask_core(struct procstat_core *core,
176     unsigned short *maskp);
177 static int      procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp,
178     unsigned short *maskp);
179 static int      procstat_getumask_sysctl(pid_t pid, unsigned short *maskp);
180 static int      vntype2psfsttype(int type);
181
182 void
183 procstat_close(struct procstat *procstat)
184 {
185
186         assert(procstat);
187         if (procstat->type == PROCSTAT_KVM)
188                 kvm_close(procstat->kd);
189         else if (procstat->type == PROCSTAT_CORE)
190                 procstat_core_close(procstat->core);
191         procstat_freeargv(procstat);
192         procstat_freeenvv(procstat);
193         free(procstat);
194 }
195
196 struct procstat *
197 procstat_open_sysctl(void)
198 {
199         struct procstat *procstat;
200
201         procstat = calloc(1, sizeof(*procstat));
202         if (procstat == NULL) {
203                 warn("malloc()");
204                 return (NULL);
205         }
206         procstat->type = PROCSTAT_SYSCTL;
207         return (procstat);
208 }
209
210 struct procstat *
211 procstat_open_kvm(const char *nlistf, const char *memf)
212 {
213         struct procstat *procstat;
214         kvm_t *kd;
215         char buf[_POSIX2_LINE_MAX];
216
217         procstat = calloc(1, sizeof(*procstat));
218         if (procstat == NULL) {
219                 warn("malloc()");
220                 return (NULL);
221         }
222         kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
223         if (kd == NULL) {
224                 warnx("kvm_openfiles(): %s", buf);
225                 free(procstat);
226                 return (NULL);
227         }
228         procstat->type = PROCSTAT_KVM;
229         procstat->kd = kd;
230         return (procstat);
231 }
232
233 struct procstat *
234 procstat_open_core(const char *filename)
235 {
236         struct procstat *procstat;
237         struct procstat_core *core;
238
239         procstat = calloc(1, sizeof(*procstat));
240         if (procstat == NULL) {
241                 warn("malloc()");
242                 return (NULL);
243         }
244         core = procstat_core_open(filename);
245         if (core == NULL) {
246                 free(procstat);
247                 return (NULL);
248         }
249         procstat->type = PROCSTAT_CORE;
250         procstat->core = core;
251         return (procstat);
252 }
253
254 struct kinfo_proc *
255 procstat_getprocs(struct procstat *procstat, int what, int arg,
256     unsigned int *count)
257 {
258         struct kinfo_proc *p0, *p;
259         size_t len, olen;
260         int name[4];
261         int cnt;
262         int error;
263
264         assert(procstat);
265         assert(count);
266         p = NULL;
267         if (procstat->type == PROCSTAT_KVM) {
268                 *count = 0;
269                 p0 = kvm_getprocs(procstat->kd, what, arg, &cnt);
270                 if (p0 == NULL || cnt <= 0)
271                         return (NULL);
272                 *count = cnt;
273                 len = *count * sizeof(*p);
274                 p = malloc(len);
275                 if (p == NULL) {
276                         warnx("malloc(%zu)", len);
277                         goto fail;
278                 }
279                 bcopy(p0, p, len);
280                 return (p);
281         } else if (procstat->type == PROCSTAT_SYSCTL) {
282                 len = 0;
283                 name[0] = CTL_KERN;
284                 name[1] = KERN_PROC;
285                 name[2] = what;
286                 name[3] = arg;
287                 error = sysctl(name, nitems(name), NULL, &len, NULL, 0);
288                 if (error < 0 && errno != EPERM) {
289                         warn("sysctl(kern.proc)");
290                         goto fail;
291                 }
292                 if (len == 0) {
293                         warnx("no processes?");
294                         goto fail;
295                 }
296                 do {
297                         len += len / 10;
298                         p = reallocf(p, len);
299                         if (p == NULL) {
300                                 warnx("reallocf(%zu)", len);
301                                 goto fail;
302                         }
303                         olen = len;
304                         error = sysctl(name, nitems(name), p, &len, NULL, 0);
305                 } while (error < 0 && errno == ENOMEM && olen == len);
306                 if (error < 0 && errno != EPERM) {
307                         warn("sysctl(kern.proc)");
308                         goto fail;
309                 }
310                 /* Perform simple consistency checks. */
311                 if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
312                         warnx("kinfo_proc structure size mismatch (len = %zu)", len);
313                         goto fail;
314                 }
315                 *count = len / sizeof(*p);
316                 return (p);
317         } else if (procstat->type == PROCSTAT_CORE) {
318                 p = procstat_core_get(procstat->core, PSC_TYPE_PROC, NULL,
319                     &len);
320                 if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
321                         warnx("kinfo_proc structure size mismatch");
322                         goto fail;
323                 }
324                 *count = len / sizeof(*p);
325                 return (p);
326         } else {
327                 warnx("unknown access method: %d", procstat->type);
328                 return (NULL);
329         }
330 fail:
331         if (p)
332                 free(p);
333         return (NULL);
334 }
335
336 void
337 procstat_freeprocs(struct procstat *procstat __unused, struct kinfo_proc *p)
338 {
339
340         if (p != NULL)
341                 free(p);
342         p = NULL;
343 }
344
345 struct filestat_list *
346 procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
347 {
348
349         switch(procstat->type) {
350         case PROCSTAT_KVM:
351                 return (procstat_getfiles_kvm(procstat, kp, mmapped));
352         case PROCSTAT_SYSCTL:
353         case PROCSTAT_CORE:
354                 return (procstat_getfiles_sysctl(procstat, kp, mmapped));
355         default:
356                 warnx("unknown access method: %d", procstat->type);
357                 return (NULL);
358         }
359 }
360
361 void
362 procstat_freefiles(struct procstat *procstat, struct filestat_list *head)
363 {
364         struct filestat *fst, *tmp;
365
366         STAILQ_FOREACH_SAFE(fst, head, next, tmp) {
367                 if (fst->fs_path != NULL)
368                         free(fst->fs_path);
369                 free(fst);
370         }
371         free(head);
372         if (procstat->vmentries != NULL) {
373                 free(procstat->vmentries);
374                 procstat->vmentries = NULL;
375         }
376         if (procstat->files != NULL) {
377                 free(procstat->files);
378                 procstat->files = NULL;
379         }
380 }
381
382 static struct filestat *
383 filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags,
384     int refcount, off_t offset, char *path, cap_rights_t *cap_rightsp)
385 {
386         struct filestat *entry;
387
388         entry = calloc(1, sizeof(*entry));
389         if (entry == NULL) {
390                 warn("malloc()");
391                 return (NULL);
392         }
393         entry->fs_typedep = typedep;
394         entry->fs_fflags = fflags;
395         entry->fs_uflags = uflags;
396         entry->fs_fd = fd;
397         entry->fs_type = type;
398         entry->fs_ref_count = refcount;
399         entry->fs_offset = offset;
400         entry->fs_path = path;
401         if (cap_rightsp != NULL)
402                 entry->fs_cap_rights = *cap_rightsp;
403         else
404                 cap_rights_init(&entry->fs_cap_rights);
405         return (entry);
406 }
407
408 static struct vnode *
409 getctty(kvm_t *kd, struct kinfo_proc *kp)
410 {
411         struct pgrp pgrp;
412         struct proc proc;
413         struct session sess;
414         int error;
415                         
416         assert(kp);
417         error = kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
418             sizeof(proc));
419         if (error == 0) {
420                 warnx("can't read proc struct at %p for pid %d",
421                     kp->ki_paddr, kp->ki_pid);
422                 return (NULL);
423         }
424         if (proc.p_pgrp == NULL)
425                 return (NULL);
426         error = kvm_read_all(kd, (unsigned long)proc.p_pgrp, &pgrp,
427             sizeof(pgrp));
428         if (error == 0) {
429                 warnx("can't read pgrp struct at %p for pid %d",
430                     proc.p_pgrp, kp->ki_pid);
431                 return (NULL);
432         }
433         error = kvm_read_all(kd, (unsigned long)pgrp.pg_session, &sess,
434             sizeof(sess));
435         if (error == 0) {
436                 warnx("can't read session struct at %p for pid %d",
437                     pgrp.pg_session, kp->ki_pid);
438                 return (NULL);
439         }
440         return (sess.s_ttyvp);
441 }
442
443 static struct filestat_list *
444 procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
445 {
446         struct file file;
447         struct filedesc filed;
448         struct vm_map_entry vmentry;
449         struct vm_object object;
450         struct vmspace vmspace;
451         vm_map_entry_t entryp;
452         vm_map_t map;
453         vm_object_t objp;
454         struct vnode *vp;
455         struct file **ofiles;
456         struct filestat *entry;
457         struct filestat_list *head;
458         kvm_t *kd;
459         void *data;
460         int i, fflags;
461         int prot, type;
462         unsigned int nfiles;
463
464         assert(procstat);
465         kd = procstat->kd;
466         if (kd == NULL)
467                 return (NULL);
468         if (kp->ki_fd == NULL)
469                 return (NULL);
470         if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed,
471             sizeof(filed))) {
472                 warnx("can't read filedesc at %p", (void *)kp->ki_fd);
473                 return (NULL);
474         }
475
476         /*
477          * Allocate list head.
478          */
479         head = malloc(sizeof(*head));
480         if (head == NULL)
481                 return (NULL);
482         STAILQ_INIT(head);
483
484         /* root directory vnode, if one. */
485         if (filed.fd_rdir) {
486                 entry = filestat_new_entry(filed.fd_rdir, PS_FST_TYPE_VNODE, -1,
487                     PS_FST_FFLAG_READ, PS_FST_UFLAG_RDIR, 0, 0, NULL, NULL);
488                 if (entry != NULL)
489                         STAILQ_INSERT_TAIL(head, entry, next);
490         }
491         /* current working directory vnode. */
492         if (filed.fd_cdir) {
493                 entry = filestat_new_entry(filed.fd_cdir, PS_FST_TYPE_VNODE, -1,
494                     PS_FST_FFLAG_READ, PS_FST_UFLAG_CDIR, 0, 0, NULL, NULL);
495                 if (entry != NULL)
496                         STAILQ_INSERT_TAIL(head, entry, next);
497         }
498         /* jail root, if any. */
499         if (filed.fd_jdir) {
500                 entry = filestat_new_entry(filed.fd_jdir, PS_FST_TYPE_VNODE, -1,
501                     PS_FST_FFLAG_READ, PS_FST_UFLAG_JAIL, 0, 0, NULL, NULL);
502                 if (entry != NULL)
503                         STAILQ_INSERT_TAIL(head, entry, next);
504         }
505         /* ktrace vnode, if one */
506         if (kp->ki_tracep) {
507                 entry = filestat_new_entry(kp->ki_tracep, PS_FST_TYPE_VNODE, -1,
508                     PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE,
509                     PS_FST_UFLAG_TRACE, 0, 0, NULL, NULL);
510                 if (entry != NULL)
511                         STAILQ_INSERT_TAIL(head, entry, next);
512         }
513         /* text vnode, if one */
514         if (kp->ki_textvp) {
515                 entry = filestat_new_entry(kp->ki_textvp, PS_FST_TYPE_VNODE, -1,
516                     PS_FST_FFLAG_READ, PS_FST_UFLAG_TEXT, 0, 0, NULL, NULL);
517                 if (entry != NULL)
518                         STAILQ_INSERT_TAIL(head, entry, next);
519         }
520         /* Controlling terminal. */
521         if ((vp = getctty(kd, kp)) != NULL) {
522                 entry = filestat_new_entry(vp, PS_FST_TYPE_VNODE, -1,
523                     PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE,
524                     PS_FST_UFLAG_CTTY, 0, 0, NULL, NULL);
525                 if (entry != NULL)
526                         STAILQ_INSERT_TAIL(head, entry, next);
527         }
528
529         nfiles = filed.fd_lastfile + 1;
530         ofiles = malloc(nfiles * sizeof(struct file *));
531         if (ofiles == NULL) {
532                 warn("malloc(%zu)", nfiles * sizeof(struct file *));
533                 goto do_mmapped;
534         }
535         if (!kvm_read_all(kd, (unsigned long)filed.fd_ofiles, ofiles,
536             nfiles * sizeof(struct file *))) {
537                 warnx("cannot read file structures at %p",
538                     (void *)filed.fd_ofiles);
539                 free(ofiles);
540                 goto do_mmapped;
541         }
542         for (i = 0; i <= filed.fd_lastfile; i++) {
543                 if (ofiles[i] == NULL)
544                         continue;
545                 if (!kvm_read_all(kd, (unsigned long)ofiles[i], &file,
546                     sizeof(struct file))) {
547                         warnx("can't read file %d at %p", i,
548                             (void *)ofiles[i]);
549                         continue;
550                 }
551                 switch (file.f_type) {
552                 case DTYPE_VNODE:
553                         type = PS_FST_TYPE_VNODE;
554                         data = file.f_vnode;
555                         break;
556                 case DTYPE_SOCKET:
557                         type = PS_FST_TYPE_SOCKET;
558                         data = file.f_data;
559                         break;
560                 case DTYPE_PIPE:
561                         type = PS_FST_TYPE_PIPE;
562                         data = file.f_data;
563                         break;
564                 case DTYPE_FIFO:
565                         type = PS_FST_TYPE_FIFO;
566                         data = file.f_vnode;
567                         break;
568 #ifdef DTYPE_PTS
569                 case DTYPE_PTS:
570                         type = PS_FST_TYPE_PTS;
571                         data = file.f_data;
572                         break;
573 #endif
574                 case DTYPE_SEM:
575                         type = PS_FST_TYPE_SEM;
576                         data = file.f_data;
577                         break;
578                 case DTYPE_SHM:
579                         type = PS_FST_TYPE_SHM;
580                         data = file.f_data;
581                         break;
582                 case DTYPE_PROCDESC:
583                         type = PS_FST_TYPE_PROCDESC;
584                         data = file.f_data;
585                         break;
586                 case DTYPE_DEV:
587                         type = PS_FST_TYPE_DEV;
588                         data = file.f_data;
589                         break;
590                 default:
591                         continue;
592                 }
593                 /* XXXRW: No capability rights support for kvm yet. */
594                 entry = filestat_new_entry(data, type, i,
595                     to_filestat_flags(file.f_flag), 0, 0, 0, NULL, NULL);
596                 if (entry != NULL)
597                         STAILQ_INSERT_TAIL(head, entry, next);
598         }
599         free(ofiles);
600
601 do_mmapped:
602
603         /*
604          * Process mmapped files if requested.
605          */
606         if (mmapped) {
607                 if (!kvm_read_all(kd, (unsigned long)kp->ki_vmspace, &vmspace,
608                     sizeof(vmspace))) {
609                         warnx("can't read vmspace at %p",
610                             (void *)kp->ki_vmspace);
611                         goto exit;
612                 }
613                 map = &vmspace.vm_map;
614
615                 for (entryp = map->header.next;
616                     entryp != &kp->ki_vmspace->vm_map.header;
617                     entryp = vmentry.next) {
618                         if (!kvm_read_all(kd, (unsigned long)entryp, &vmentry,
619                             sizeof(vmentry))) {
620                                 warnx("can't read vm_map_entry at %p",
621                                     (void *)entryp);
622                                 continue;
623                         }
624                         if (vmentry.eflags & MAP_ENTRY_IS_SUB_MAP)
625                                 continue;
626                         if ((objp = vmentry.object.vm_object) == NULL)
627                                 continue;
628                         for (; objp; objp = object.backing_object) {
629                                 if (!kvm_read_all(kd, (unsigned long)objp,
630                                     &object, sizeof(object))) {
631                                         warnx("can't read vm_object at %p",
632                                             (void *)objp);
633                                         break;
634                                 }
635                         }
636
637                         /* We want only vnode objects. */
638                         if (object.type != OBJT_VNODE)
639                                 continue;
640
641                         prot = vmentry.protection;
642                         fflags = 0;
643                         if (prot & VM_PROT_READ)
644                                 fflags = PS_FST_FFLAG_READ;
645                         if ((vmentry.eflags & MAP_ENTRY_COW) == 0 &&
646                             prot & VM_PROT_WRITE)
647                                 fflags |= PS_FST_FFLAG_WRITE;
648
649                         /*
650                          * Create filestat entry.
651                          */
652                         entry = filestat_new_entry(object.handle,
653                             PS_FST_TYPE_VNODE, -1, fflags,
654                             PS_FST_UFLAG_MMAP, 0, 0, NULL, NULL);
655                         if (entry != NULL)
656                                 STAILQ_INSERT_TAIL(head, entry, next);
657                 }
658         }
659 exit:
660         return (head);
661 }
662
663 /*
664  * kinfo types to filestat translation.
665  */
666 static int
667 kinfo_type2fst(int kftype)
668 {
669         static struct {
670                 int     kf_type;
671                 int     fst_type;
672         } kftypes2fst[] = {
673                 { KF_TYPE_PROCDESC, PS_FST_TYPE_PROCDESC },
674                 { KF_TYPE_CRYPTO, PS_FST_TYPE_CRYPTO },
675                 { KF_TYPE_DEV, PS_FST_TYPE_DEV },
676                 { KF_TYPE_FIFO, PS_FST_TYPE_FIFO },
677                 { KF_TYPE_KQUEUE, PS_FST_TYPE_KQUEUE },
678                 { KF_TYPE_MQUEUE, PS_FST_TYPE_MQUEUE },
679                 { KF_TYPE_NONE, PS_FST_TYPE_NONE },
680                 { KF_TYPE_PIPE, PS_FST_TYPE_PIPE },
681                 { KF_TYPE_PTS, PS_FST_TYPE_PTS },
682                 { KF_TYPE_SEM, PS_FST_TYPE_SEM },
683                 { KF_TYPE_SHM, PS_FST_TYPE_SHM },
684                 { KF_TYPE_SOCKET, PS_FST_TYPE_SOCKET },
685                 { KF_TYPE_VNODE, PS_FST_TYPE_VNODE },
686                 { KF_TYPE_UNKNOWN, PS_FST_TYPE_UNKNOWN }
687         };
688 #define NKFTYPES        (sizeof(kftypes2fst) / sizeof(*kftypes2fst))
689         unsigned int i;
690
691         for (i = 0; i < NKFTYPES; i++)
692                 if (kftypes2fst[i].kf_type == kftype)
693                         break;
694         if (i == NKFTYPES)
695                 return (PS_FST_TYPE_UNKNOWN);
696         return (kftypes2fst[i].fst_type);
697 }
698
699 /*
700  * kinfo flags to filestat translation.
701  */
702 static int
703 kinfo_fflags2fst(int kfflags)
704 {
705         static struct {
706                 int     kf_flag;
707                 int     fst_flag;
708         } kfflags2fst[] = {
709                 { KF_FLAG_APPEND, PS_FST_FFLAG_APPEND },
710                 { KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC },
711                 { KF_FLAG_CREAT, PS_FST_FFLAG_CREAT },
712                 { KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT },
713                 { KF_FLAG_EXCL, PS_FST_FFLAG_EXCL },
714                 { KF_FLAG_EXEC, PS_FST_FFLAG_EXEC },
715                 { KF_FLAG_EXLOCK, PS_FST_FFLAG_EXLOCK },
716                 { KF_FLAG_FSYNC, PS_FST_FFLAG_SYNC },
717                 { KF_FLAG_HASLOCK, PS_FST_FFLAG_HASLOCK },
718                 { KF_FLAG_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW },
719                 { KF_FLAG_NONBLOCK, PS_FST_FFLAG_NONBLOCK },
720                 { KF_FLAG_READ, PS_FST_FFLAG_READ },
721                 { KF_FLAG_SHLOCK, PS_FST_FFLAG_SHLOCK },
722                 { KF_FLAG_TRUNC, PS_FST_FFLAG_TRUNC },
723                 { KF_FLAG_WRITE, PS_FST_FFLAG_WRITE }
724         };
725 #define NKFFLAGS        (sizeof(kfflags2fst) / sizeof(*kfflags2fst))
726         unsigned int i;
727         int flags;
728
729         flags = 0;
730         for (i = 0; i < NKFFLAGS; i++)
731                 if ((kfflags & kfflags2fst[i].kf_flag) != 0)
732                         flags |= kfflags2fst[i].fst_flag;
733         return (flags);
734 }
735
736 static int
737 kinfo_uflags2fst(int fd)
738 {
739
740         switch (fd) {
741         case KF_FD_TYPE_CTTY:
742                 return (PS_FST_UFLAG_CTTY);
743         case KF_FD_TYPE_CWD:
744                 return (PS_FST_UFLAG_CDIR);
745         case KF_FD_TYPE_JAIL:
746                 return (PS_FST_UFLAG_JAIL);
747         case KF_FD_TYPE_TEXT:
748                 return (PS_FST_UFLAG_TEXT);
749         case KF_FD_TYPE_TRACE:
750                 return (PS_FST_UFLAG_TRACE);
751         case KF_FD_TYPE_ROOT:
752                 return (PS_FST_UFLAG_RDIR);
753         }
754         return (0);
755 }
756
757 static struct kinfo_file *
758 kinfo_getfile_core(struct procstat_core *core, int *cntp)
759 {
760         int cnt;
761         size_t len;
762         char *buf, *bp, *eb;
763         struct kinfo_file *kif, *kp, *kf;
764
765         buf = procstat_core_get(core, PSC_TYPE_FILES, NULL, &len);
766         if (buf == NULL)
767                 return (NULL);
768         /*
769          * XXXMG: The code below is just copy&past from libutil.
770          * The code duplication can be avoided if libutil
771          * is extended to provide something like:
772          *   struct kinfo_file *kinfo_getfile_from_buf(const char *buf,
773          *       size_t len, int *cntp);
774          */
775
776         /* Pass 1: count items */
777         cnt = 0;
778         bp = buf;
779         eb = buf + len;
780         while (bp < eb) {
781                 kf = (struct kinfo_file *)(uintptr_t)bp;
782                 if (kf->kf_structsize == 0)
783                         break;
784                 bp += kf->kf_structsize;
785                 cnt++;
786         }
787
788         kif = calloc(cnt, sizeof(*kif));
789         if (kif == NULL) {
790                 free(buf);
791                 return (NULL);
792         }
793         bp = buf;
794         eb = buf + len;
795         kp = kif;
796         /* Pass 2: unpack */
797         while (bp < eb) {
798                 kf = (struct kinfo_file *)(uintptr_t)bp;
799                 if (kf->kf_structsize == 0)
800                         break;
801                 /* Copy/expand into pre-zeroed buffer */
802                 memcpy(kp, kf, kf->kf_structsize);
803                 /* Advance to next packed record */
804                 bp += kf->kf_structsize;
805                 /* Set field size to fixed length, advance */
806                 kp->kf_structsize = sizeof(*kp);
807                 kp++;
808         }
809         free(buf);
810         *cntp = cnt;
811         return (kif);   /* Caller must free() return value */
812 }
813
814 static struct filestat_list *
815 procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp,
816     int mmapped)
817 {
818         struct kinfo_file *kif, *files;
819         struct kinfo_vmentry *kve, *vmentries;
820         struct filestat_list *head;
821         struct filestat *entry;
822         char *path;
823         off_t offset;
824         int cnt, fd, fflags;
825         int i, type, uflags;
826         int refcount;
827         cap_rights_t cap_rights;
828
829         assert(kp);
830         if (kp->ki_fd == NULL)
831                 return (NULL);
832         switch(procstat->type) {
833         case PROCSTAT_SYSCTL:
834                 files = kinfo_getfile(kp->ki_pid, &cnt);
835                 break;
836         case PROCSTAT_CORE:
837                 files = kinfo_getfile_core(procstat->core, &cnt);
838                 break;
839         default:
840                 assert(!"invalid type");
841         }
842         if (files == NULL && errno != EPERM) {
843                 warn("kinfo_getfile()");
844                 return (NULL);
845         }
846         procstat->files = files;
847
848         /*
849          * Allocate list head.
850          */
851         head = malloc(sizeof(*head));
852         if (head == NULL)
853                 return (NULL);
854         STAILQ_INIT(head);
855         for (i = 0; i < cnt; i++) {
856                 kif = &files[i];
857
858                 type = kinfo_type2fst(kif->kf_type);
859                 fd = kif->kf_fd >= 0 ? kif->kf_fd : -1;
860                 fflags = kinfo_fflags2fst(kif->kf_flags);
861                 uflags = kinfo_uflags2fst(kif->kf_fd);
862                 refcount = kif->kf_ref_count;
863                 offset = kif->kf_offset;
864                 if (*kif->kf_path != '\0')
865                         path = strdup(kif->kf_path);
866                 else
867                         path = NULL;
868                 cap_rights = kif->kf_cap_rights;
869
870                 /*
871                  * Create filestat entry.
872                  */
873                 entry = filestat_new_entry(kif, type, fd, fflags, uflags,
874                     refcount, offset, path, &cap_rights);
875                 if (entry != NULL)
876                         STAILQ_INSERT_TAIL(head, entry, next);
877         }
878         if (mmapped != 0) {
879                 vmentries = procstat_getvmmap(procstat, kp, &cnt);
880                 procstat->vmentries = vmentries;
881                 if (vmentries == NULL || cnt == 0)
882                         goto fail;
883                 for (i = 0; i < cnt; i++) {
884                         kve = &vmentries[i];
885                         if (kve->kve_type != KVME_TYPE_VNODE)
886                                 continue;
887                         fflags = 0;
888                         if (kve->kve_protection & KVME_PROT_READ)
889                                 fflags = PS_FST_FFLAG_READ;
890                         if ((kve->kve_flags & KVME_FLAG_COW) == 0 &&
891                             kve->kve_protection & KVME_PROT_WRITE)
892                                 fflags |= PS_FST_FFLAG_WRITE;
893                         offset = kve->kve_offset;
894                         refcount = kve->kve_ref_count;
895                         if (*kve->kve_path != '\0')
896                                 path = strdup(kve->kve_path);
897                         else
898                                 path = NULL;
899                         entry = filestat_new_entry(kve, PS_FST_TYPE_VNODE, -1,
900                             fflags, PS_FST_UFLAG_MMAP, refcount, offset, path,
901                             NULL);
902                         if (entry != NULL)
903                                 STAILQ_INSERT_TAIL(head, entry, next);
904                 }
905         }
906 fail:
907         return (head);
908 }
909
910 int
911 procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst,
912     struct pipestat *ps, char *errbuf)
913 {
914
915         assert(ps);
916         if (procstat->type == PROCSTAT_KVM) {
917                 return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps,
918                     errbuf));
919         } else if (procstat->type == PROCSTAT_SYSCTL ||
920                 procstat->type == PROCSTAT_CORE) {
921                 return (procstat_get_pipe_info_sysctl(fst, ps, errbuf));
922         } else {
923                 warnx("unknown access method: %d", procstat->type);
924                 if (errbuf != NULL)
925                         snprintf(errbuf, _POSIX2_LINE_MAX, "error");
926                 return (1);
927         }
928 }
929
930 static int
931 procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst,
932     struct pipestat *ps, char *errbuf)
933 {
934         struct pipe pi;
935         void *pipep;
936
937         assert(kd);
938         assert(ps);
939         assert(fst);
940         bzero(ps, sizeof(*ps));
941         pipep = fst->fs_typedep;
942         if (pipep == NULL)
943                 goto fail;
944         if (!kvm_read_all(kd, (unsigned long)pipep, &pi, sizeof(struct pipe))) {
945                 warnx("can't read pipe at %p", (void *)pipep);
946                 goto fail;
947         }
948         ps->addr = (uintptr_t)pipep;
949         ps->peer = (uintptr_t)pi.pipe_peer;
950         ps->buffer_cnt = pi.pipe_buffer.cnt;
951         return (0);
952
953 fail:
954         if (errbuf != NULL)
955                 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
956         return (1);
957 }
958
959 static int
960 procstat_get_pipe_info_sysctl(struct filestat *fst, struct pipestat *ps,
961     char *errbuf __unused)
962 {
963         struct kinfo_file *kif;
964
965         assert(ps);
966         assert(fst);
967         bzero(ps, sizeof(*ps));
968         kif = fst->fs_typedep;
969         if (kif == NULL)
970                 return (1);
971         ps->addr = kif->kf_un.kf_pipe.kf_pipe_addr;
972         ps->peer = kif->kf_un.kf_pipe.kf_pipe_peer;
973         ps->buffer_cnt = kif->kf_un.kf_pipe.kf_pipe_buffer_cnt;
974         return (0);
975 }
976
977 int
978 procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,
979     struct ptsstat *pts, char *errbuf)
980 {
981
982         assert(pts);
983         if (procstat->type == PROCSTAT_KVM) {
984                 return (procstat_get_pts_info_kvm(procstat->kd, fst, pts,
985                     errbuf));
986         } else if (procstat->type == PROCSTAT_SYSCTL ||
987                 procstat->type == PROCSTAT_CORE) {
988                 return (procstat_get_pts_info_sysctl(fst, pts, errbuf));
989         } else {
990                 warnx("unknown access method: %d", procstat->type);
991                 if (errbuf != NULL)
992                         snprintf(errbuf, _POSIX2_LINE_MAX, "error");
993                 return (1);
994         }
995 }
996
997 static int
998 procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst,
999     struct ptsstat *pts, char *errbuf)
1000 {
1001         struct tty tty;
1002         void *ttyp;
1003
1004         assert(kd);
1005         assert(pts);
1006         assert(fst);
1007         bzero(pts, sizeof(*pts));
1008         ttyp = fst->fs_typedep;
1009         if (ttyp == NULL)
1010                 goto fail;
1011         if (!kvm_read_all(kd, (unsigned long)ttyp, &tty, sizeof(struct tty))) {
1012                 warnx("can't read tty at %p", (void *)ttyp);
1013                 goto fail;
1014         }
1015         pts->dev = dev2udev(kd, tty.t_dev);
1016         (void)kdevtoname(kd, tty.t_dev, pts->devname);
1017         return (0);
1018
1019 fail:
1020         if (errbuf != NULL)
1021                 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1022         return (1);
1023 }
1024
1025 static int
1026 procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts,
1027     char *errbuf __unused)
1028 {
1029         struct kinfo_file *kif;
1030
1031         assert(pts);
1032         assert(fst);
1033         bzero(pts, sizeof(*pts));
1034         kif = fst->fs_typedep;
1035         if (kif == NULL)
1036                 return (0);
1037         pts->dev = kif->kf_un.kf_pts.kf_pts_dev;
1038         strlcpy(pts->devname, kif->kf_path, sizeof(pts->devname));
1039         return (0);
1040 }
1041
1042 int
1043 procstat_get_sem_info(struct procstat *procstat, struct filestat *fst,
1044     struct semstat *sem, char *errbuf)
1045 {
1046
1047         assert(sem);
1048         if (procstat->type == PROCSTAT_KVM) {
1049                 return (procstat_get_sem_info_kvm(procstat->kd, fst, sem,
1050                     errbuf));
1051         } else if (procstat->type == PROCSTAT_SYSCTL ||
1052             procstat->type == PROCSTAT_CORE) {
1053                 return (procstat_get_sem_info_sysctl(fst, sem, errbuf));
1054         } else {
1055                 warnx("unknown access method: %d", procstat->type);
1056                 if (errbuf != NULL)
1057                         snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1058                 return (1);
1059         }
1060 }
1061
1062 static int
1063 procstat_get_sem_info_kvm(kvm_t *kd, struct filestat *fst,
1064     struct semstat *sem, char *errbuf)
1065 {
1066         struct ksem ksem;
1067         void *ksemp;
1068         char *path;
1069         int i;
1070
1071         assert(kd);
1072         assert(sem);
1073         assert(fst);
1074         bzero(sem, sizeof(*sem));
1075         ksemp = fst->fs_typedep;
1076         if (ksemp == NULL)
1077                 goto fail;
1078         if (!kvm_read_all(kd, (unsigned long)ksemp, &ksem,
1079             sizeof(struct ksem))) {
1080                 warnx("can't read ksem at %p", (void *)ksemp);
1081                 goto fail;
1082         }
1083         sem->mode = S_IFREG | ksem.ks_mode;
1084         sem->value = ksem.ks_value;
1085         if (fst->fs_path == NULL && ksem.ks_path != NULL) {
1086                 path = malloc(MAXPATHLEN);
1087                 for (i = 0; i < MAXPATHLEN - 1; i++) {
1088                         if (!kvm_read_all(kd, (unsigned long)ksem.ks_path + i,
1089                             path + i, 1))
1090                                 break;
1091                         if (path[i] == '\0')
1092                                 break;
1093                 }
1094                 path[i] = '\0';
1095                 if (i == 0)
1096                         free(path);
1097                 else
1098                         fst->fs_path = path;
1099         }
1100         return (0);
1101
1102 fail:
1103         if (errbuf != NULL)
1104                 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1105         return (1);
1106 }
1107
1108 static int
1109 procstat_get_sem_info_sysctl(struct filestat *fst, struct semstat *sem,
1110     char *errbuf __unused)
1111 {
1112         struct kinfo_file *kif;
1113
1114         assert(sem);
1115         assert(fst);
1116         bzero(sem, sizeof(*sem));
1117         kif = fst->fs_typedep;
1118         if (kif == NULL)
1119                 return (0);
1120         sem->value = kif->kf_un.kf_sem.kf_sem_value;
1121         sem->mode = kif->kf_un.kf_sem.kf_sem_mode;
1122         return (0);
1123 }
1124
1125 int
1126 procstat_get_shm_info(struct procstat *procstat, struct filestat *fst,
1127     struct shmstat *shm, char *errbuf)
1128 {
1129
1130         assert(shm);
1131         if (procstat->type == PROCSTAT_KVM) {
1132                 return (procstat_get_shm_info_kvm(procstat->kd, fst, shm,
1133                     errbuf));
1134         } else if (procstat->type == PROCSTAT_SYSCTL ||
1135             procstat->type == PROCSTAT_CORE) {
1136                 return (procstat_get_shm_info_sysctl(fst, shm, errbuf));
1137         } else {
1138                 warnx("unknown access method: %d", procstat->type);
1139                 if (errbuf != NULL)
1140                         snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1141                 return (1);
1142         }
1143 }
1144
1145 static int
1146 procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst,
1147     struct shmstat *shm, char *errbuf)
1148 {
1149         struct shmfd shmfd;
1150         void *shmfdp;
1151         char *path;
1152         int i;
1153
1154         assert(kd);
1155         assert(shm);
1156         assert(fst);
1157         bzero(shm, sizeof(*shm));
1158         shmfdp = fst->fs_typedep;
1159         if (shmfdp == NULL)
1160                 goto fail;
1161         if (!kvm_read_all(kd, (unsigned long)shmfdp, &shmfd,
1162             sizeof(struct shmfd))) {
1163                 warnx("can't read shmfd at %p", (void *)shmfdp);
1164                 goto fail;
1165         }
1166         shm->mode = S_IFREG | shmfd.shm_mode;
1167         shm->size = shmfd.shm_size;
1168         if (fst->fs_path == NULL && shmfd.shm_path != NULL) {
1169                 path = malloc(MAXPATHLEN);
1170                 for (i = 0; i < MAXPATHLEN - 1; i++) {
1171                         if (!kvm_read_all(kd, (unsigned long)shmfd.shm_path + i,
1172                             path + i, 1))
1173                                 break;
1174                         if (path[i] == '\0')
1175                                 break;
1176                 }
1177                 path[i] = '\0';
1178                 if (i == 0)
1179                         free(path);
1180                 else
1181                         fst->fs_path = path;
1182         }
1183         return (0);
1184
1185 fail:
1186         if (errbuf != NULL)
1187                 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1188         return (1);
1189 }
1190
1191 static int
1192 procstat_get_shm_info_sysctl(struct filestat *fst, struct shmstat *shm,
1193     char *errbuf __unused)
1194 {
1195         struct kinfo_file *kif;
1196
1197         assert(shm);
1198         assert(fst);
1199         bzero(shm, sizeof(*shm));
1200         kif = fst->fs_typedep;
1201         if (kif == NULL)
1202                 return (0);
1203         shm->size = kif->kf_un.kf_file.kf_file_size;
1204         shm->mode = kif->kf_un.kf_file.kf_file_mode;
1205         return (0);
1206 }
1207
1208 int
1209 procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
1210     struct vnstat *vn, char *errbuf)
1211 {
1212
1213         assert(vn);
1214         if (procstat->type == PROCSTAT_KVM) {
1215                 return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn,
1216                     errbuf));
1217         } else if (procstat->type == PROCSTAT_SYSCTL ||
1218                 procstat->type == PROCSTAT_CORE) {
1219                 return (procstat_get_vnode_info_sysctl(fst, vn, errbuf));
1220         } else {
1221                 warnx("unknown access method: %d", procstat->type);
1222                 if (errbuf != NULL)
1223                         snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1224                 return (1);
1225         }
1226 }
1227
1228 static int
1229 procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
1230     struct vnstat *vn, char *errbuf)
1231 {
1232         /* Filesystem specific handlers. */
1233         #define FSTYPE(fst)     {#fst, fst##_filestat}
1234         struct {
1235                 const char      *tag;
1236                 int             (*handler)(kvm_t *kd, struct vnode *vp,
1237                     struct vnstat *vn);
1238         } fstypes[] = {
1239                 FSTYPE(devfs),
1240                 FSTYPE(isofs),
1241                 FSTYPE(msdosfs),
1242                 FSTYPE(nfs),
1243                 FSTYPE(smbfs),
1244                 FSTYPE(udf), 
1245                 FSTYPE(ufs),
1246 #ifdef LIBPROCSTAT_ZFS
1247                 FSTYPE(zfs),
1248 #endif
1249         };
1250 #define NTYPES  (sizeof(fstypes) / sizeof(*fstypes))
1251         struct vnode vnode;
1252         char tagstr[12];
1253         void *vp;
1254         int error;
1255         unsigned int i;
1256
1257         assert(kd);
1258         assert(vn);
1259         assert(fst);
1260         vp = fst->fs_typedep;
1261         if (vp == NULL)
1262                 goto fail;
1263         error = kvm_read_all(kd, (unsigned long)vp, &vnode, sizeof(vnode));
1264         if (error == 0) {
1265                 warnx("can't read vnode at %p", (void *)vp);
1266                 goto fail;
1267         }
1268         bzero(vn, sizeof(*vn));
1269         vn->vn_type = vntype2psfsttype(vnode.v_type);
1270         if (vnode.v_type == VNON || vnode.v_type == VBAD)
1271                 return (0);
1272         error = kvm_read_all(kd, (unsigned long)vnode.v_tag, tagstr,
1273             sizeof(tagstr));
1274         if (error == 0) {
1275                 warnx("can't read v_tag at %p", (void *)vp);
1276                 goto fail;
1277         }
1278         tagstr[sizeof(tagstr) - 1] = '\0';
1279
1280         /*
1281          * Find appropriate handler.
1282          */
1283         for (i = 0; i < NTYPES; i++)
1284                 if (!strcmp(fstypes[i].tag, tagstr)) {
1285                         if (fstypes[i].handler(kd, &vnode, vn) != 0) {
1286                                 goto fail;
1287                         }
1288                         break;
1289                 }
1290         if (i == NTYPES) {
1291                 if (errbuf != NULL)
1292                         snprintf(errbuf, _POSIX2_LINE_MAX, "?(%s)", tagstr);
1293                 return (1);
1294         }
1295         vn->vn_mntdir = getmnton(kd, vnode.v_mount);
1296         if ((vnode.v_type == VBLK || vnode.v_type == VCHR) &&
1297             vnode.v_rdev != NULL){
1298                 vn->vn_dev = dev2udev(kd, vnode.v_rdev);
1299                 (void)kdevtoname(kd, vnode.v_rdev, vn->vn_devname);
1300         } else {
1301                 vn->vn_dev = -1;
1302         }
1303         return (0);
1304
1305 fail:
1306         if (errbuf != NULL)
1307                 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1308         return (1);
1309 }
1310
1311 /*
1312  * kinfo vnode type to filestat translation.
1313  */
1314 static int
1315 kinfo_vtype2fst(int kfvtype)
1316 {
1317         static struct {
1318                 int     kf_vtype; 
1319                 int     fst_vtype;
1320         } kfvtypes2fst[] = {
1321                 { KF_VTYPE_VBAD, PS_FST_VTYPE_VBAD },
1322                 { KF_VTYPE_VBLK, PS_FST_VTYPE_VBLK },
1323                 { KF_VTYPE_VCHR, PS_FST_VTYPE_VCHR },
1324                 { KF_VTYPE_VDIR, PS_FST_VTYPE_VDIR },
1325                 { KF_VTYPE_VFIFO, PS_FST_VTYPE_VFIFO },
1326                 { KF_VTYPE_VLNK, PS_FST_VTYPE_VLNK },
1327                 { KF_VTYPE_VNON, PS_FST_VTYPE_VNON },
1328                 { KF_VTYPE_VREG, PS_FST_VTYPE_VREG },
1329                 { KF_VTYPE_VSOCK, PS_FST_VTYPE_VSOCK }
1330         };
1331 #define NKFVTYPES       (sizeof(kfvtypes2fst) / sizeof(*kfvtypes2fst))
1332         unsigned int i;
1333
1334         for (i = 0; i < NKFVTYPES; i++)
1335                 if (kfvtypes2fst[i].kf_vtype == kfvtype)
1336                         break;
1337         if (i == NKFVTYPES)
1338                 return (PS_FST_VTYPE_UNKNOWN);
1339         return (kfvtypes2fst[i].fst_vtype);
1340 }
1341
1342 static int
1343 procstat_get_vnode_info_sysctl(struct filestat *fst, struct vnstat *vn,
1344     char *errbuf)
1345 {
1346         struct statfs stbuf;
1347         struct kinfo_file *kif;
1348         struct kinfo_vmentry *kve;
1349         uint64_t fileid;
1350         uint64_t size;
1351         char *name, *path;
1352         uint32_t fsid;
1353         uint16_t mode;
1354         uint32_t rdev;
1355         int vntype;
1356         int status;
1357
1358         assert(fst);
1359         assert(vn);
1360         bzero(vn, sizeof(*vn));
1361         if (fst->fs_typedep == NULL)
1362                 return (1);
1363         if (fst->fs_uflags & PS_FST_UFLAG_MMAP) {
1364                 kve = fst->fs_typedep;
1365                 fileid = kve->kve_vn_fileid;
1366                 fsid = kve->kve_vn_fsid;
1367                 mode = kve->kve_vn_mode;
1368                 path = kve->kve_path;
1369                 rdev = kve->kve_vn_rdev;
1370                 size = kve->kve_vn_size;
1371                 vntype = kinfo_vtype2fst(kve->kve_vn_type);
1372                 status = kve->kve_status;
1373         } else {
1374                 kif = fst->fs_typedep;
1375                 fileid = kif->kf_un.kf_file.kf_file_fileid;
1376                 fsid = kif->kf_un.kf_file.kf_file_fsid;
1377                 mode = kif->kf_un.kf_file.kf_file_mode;
1378                 path = kif->kf_path;
1379                 rdev = kif->kf_un.kf_file.kf_file_rdev;
1380                 size = kif->kf_un.kf_file.kf_file_size;
1381                 vntype = kinfo_vtype2fst(kif->kf_vnode_type);
1382                 status = kif->kf_status;
1383         }
1384         vn->vn_type = vntype;
1385         if (vntype == PS_FST_VTYPE_VNON || vntype == PS_FST_VTYPE_VBAD)
1386                 return (0);
1387         if ((status & KF_ATTR_VALID) == 0) {
1388                 if (errbuf != NULL) {
1389                         snprintf(errbuf, _POSIX2_LINE_MAX,
1390                             "? (no info available)");
1391                 }
1392                 return (1);
1393         }
1394         if (path && *path) {
1395                 statfs(path, &stbuf);
1396                 vn->vn_mntdir = strdup(stbuf.f_mntonname);
1397         } else
1398                 vn->vn_mntdir = strdup("-");
1399         vn->vn_dev = rdev;
1400         if (vntype == PS_FST_VTYPE_VBLK) {
1401                 name = devname(rdev, S_IFBLK);
1402                 if (name != NULL)
1403                         strlcpy(vn->vn_devname, name,
1404                             sizeof(vn->vn_devname));
1405         } else if (vntype == PS_FST_VTYPE_VCHR) {
1406                 name = devname(vn->vn_dev, S_IFCHR);
1407                 if (name != NULL)
1408                         strlcpy(vn->vn_devname, name,
1409                             sizeof(vn->vn_devname));
1410         }
1411         vn->vn_fsid = fsid;
1412         vn->vn_fileid = fileid;
1413         vn->vn_size = size;
1414         vn->vn_mode = mode;
1415         return (0);
1416 }
1417
1418 int
1419 procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
1420     struct sockstat *sock, char *errbuf)
1421 {
1422
1423         assert(sock);
1424         if (procstat->type == PROCSTAT_KVM) {
1425                 return (procstat_get_socket_info_kvm(procstat->kd, fst, sock,
1426                     errbuf));
1427         } else if (procstat->type == PROCSTAT_SYSCTL ||
1428                 procstat->type == PROCSTAT_CORE) {
1429                 return (procstat_get_socket_info_sysctl(fst, sock, errbuf));
1430         } else {
1431                 warnx("unknown access method: %d", procstat->type);
1432                 if (errbuf != NULL)
1433                         snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1434                 return (1);
1435         }
1436 }
1437
1438 static int
1439 procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst,
1440     struct sockstat *sock, char *errbuf)
1441 {
1442         struct domain dom;
1443         struct inpcb inpcb;
1444         struct protosw proto;
1445         struct socket s;
1446         struct unpcb unpcb;
1447         ssize_t len;
1448         void *so;
1449
1450         assert(kd);
1451         assert(sock);
1452         assert(fst);
1453         bzero(sock, sizeof(*sock));
1454         so = fst->fs_typedep;
1455         if (so == NULL)
1456                 goto fail;
1457         sock->so_addr = (uintptr_t)so;
1458         /* fill in socket */
1459         if (!kvm_read_all(kd, (unsigned long)so, &s,
1460             sizeof(struct socket))) {
1461                 warnx("can't read sock at %p", (void *)so);
1462                 goto fail;
1463         }
1464         /* fill in protosw entry */
1465         if (!kvm_read_all(kd, (unsigned long)s.so_proto, &proto,
1466             sizeof(struct protosw))) {
1467                 warnx("can't read protosw at %p", (void *)s.so_proto);
1468                 goto fail;
1469         }
1470         /* fill in domain */
1471         if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom,
1472             sizeof(struct domain))) {
1473                 warnx("can't read domain at %p",
1474                     (void *)proto.pr_domain);
1475                 goto fail;
1476         }
1477         if ((len = kvm_read(kd, (unsigned long)dom.dom_name, sock->dname,
1478             sizeof(sock->dname) - 1)) < 0) {
1479                 warnx("can't read domain name at %p", (void *)dom.dom_name);
1480                 sock->dname[0] = '\0';
1481         }
1482         else
1483                 sock->dname[len] = '\0';
1484         
1485         /*
1486          * Fill in known data.
1487          */
1488         sock->type = s.so_type;
1489         sock->proto = proto.pr_protocol;
1490         sock->dom_family = dom.dom_family;
1491         sock->so_pcb = (uintptr_t)s.so_pcb;
1492
1493         /*
1494          * Protocol specific data.
1495          */
1496         switch(dom.dom_family) {
1497         case AF_INET:
1498         case AF_INET6:
1499                 if (proto.pr_protocol == IPPROTO_TCP) {
1500                         if (s.so_pcb) {
1501                                 if (kvm_read(kd, (u_long)s.so_pcb,
1502                                     (char *)&inpcb, sizeof(struct inpcb))
1503                                     != sizeof(struct inpcb)) {
1504                                         warnx("can't read inpcb at %p",
1505                                             (void *)s.so_pcb);
1506                                 } else
1507                                         sock->inp_ppcb =
1508                                             (uintptr_t)inpcb.inp_ppcb;
1509                         }
1510                 }
1511                 break;
1512         case AF_UNIX:
1513                 if (s.so_pcb) {
1514                         if (kvm_read(kd, (u_long)s.so_pcb, (char *)&unpcb,
1515                             sizeof(struct unpcb)) != sizeof(struct unpcb)){
1516                                 warnx("can't read unpcb at %p",
1517                                     (void *)s.so_pcb);
1518                         } else if (unpcb.unp_conn) {
1519                                 sock->so_rcv_sb_state = s.so_rcv.sb_state;
1520                                 sock->so_snd_sb_state = s.so_snd.sb_state;
1521                                 sock->unp_conn = (uintptr_t)unpcb.unp_conn;
1522                         }
1523                 }
1524                 break;
1525         default:
1526                 break;
1527         }
1528         return (0);
1529
1530 fail:
1531         if (errbuf != NULL)
1532                 snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1533         return (1);
1534 }
1535
1536 static int
1537 procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock,
1538     char *errbuf __unused)
1539 {
1540         struct kinfo_file *kif;
1541
1542         assert(sock);
1543         assert(fst);
1544         bzero(sock, sizeof(*sock));
1545         kif = fst->fs_typedep;
1546         if (kif == NULL)
1547                 return (0);
1548
1549         /*
1550          * Fill in known data.
1551          */
1552         sock->type = kif->kf_sock_type;
1553         sock->proto = kif->kf_sock_protocol;
1554         sock->dom_family = kif->kf_sock_domain;
1555         sock->so_pcb = kif->kf_un.kf_sock.kf_sock_pcb;
1556         strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname));
1557         bcopy(&kif->kf_sa_local, &sock->sa_local, kif->kf_sa_local.ss_len);
1558         bcopy(&kif->kf_sa_peer, &sock->sa_peer, kif->kf_sa_peer.ss_len);
1559
1560         /*
1561          * Protocol specific data.
1562          */
1563         switch(sock->dom_family) {
1564         case AF_INET:
1565         case AF_INET6:
1566                 if (sock->proto == IPPROTO_TCP)
1567                         sock->inp_ppcb = kif->kf_un.kf_sock.kf_sock_inpcb;
1568                 break;
1569         case AF_UNIX:
1570                 if (kif->kf_un.kf_sock.kf_sock_unpconn != 0) {
1571                                 sock->so_rcv_sb_state =
1572                                     kif->kf_un.kf_sock.kf_sock_rcv_sb_state;
1573                                 sock->so_snd_sb_state =
1574                                     kif->kf_un.kf_sock.kf_sock_snd_sb_state;
1575                                 sock->unp_conn =
1576                                     kif->kf_un.kf_sock.kf_sock_unpconn;
1577                 }
1578                 break;
1579         default:
1580                 break;
1581         }
1582         return (0);
1583 }
1584
1585 /*
1586  * Descriptor flags to filestat translation.
1587  */
1588 static int
1589 to_filestat_flags(int flags)
1590 {
1591         static struct {
1592                 int flag;
1593                 int fst_flag;
1594         } fstflags[] = {
1595                 { FREAD, PS_FST_FFLAG_READ },
1596                 { FWRITE, PS_FST_FFLAG_WRITE },
1597                 { O_APPEND, PS_FST_FFLAG_APPEND },
1598                 { O_ASYNC, PS_FST_FFLAG_ASYNC },
1599                 { O_CREAT, PS_FST_FFLAG_CREAT },
1600                 { O_DIRECT, PS_FST_FFLAG_DIRECT },
1601                 { O_EXCL, PS_FST_FFLAG_EXCL },
1602                 { O_EXEC, PS_FST_FFLAG_EXEC },
1603                 { O_EXLOCK, PS_FST_FFLAG_EXLOCK },
1604                 { O_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW },
1605                 { O_NONBLOCK, PS_FST_FFLAG_NONBLOCK },
1606                 { O_SHLOCK, PS_FST_FFLAG_SHLOCK },
1607                 { O_SYNC, PS_FST_FFLAG_SYNC },
1608                 { O_TRUNC, PS_FST_FFLAG_TRUNC }
1609         };
1610 #define NFSTFLAGS       (sizeof(fstflags) / sizeof(*fstflags))
1611         int fst_flags;
1612         unsigned int i;
1613
1614         fst_flags = 0;
1615         for (i = 0; i < NFSTFLAGS; i++)
1616                 if (flags & fstflags[i].flag)
1617                         fst_flags |= fstflags[i].fst_flag;
1618         return (fst_flags);
1619 }
1620
1621 /*
1622  * Vnode type to filestate translation.
1623  */
1624 static int
1625 vntype2psfsttype(int type)
1626 {
1627         static struct {
1628                 int     vtype; 
1629                 int     fst_vtype;
1630         } vt2fst[] = {
1631                 { VBAD, PS_FST_VTYPE_VBAD },
1632                 { VBLK, PS_FST_VTYPE_VBLK },
1633                 { VCHR, PS_FST_VTYPE_VCHR },
1634                 { VDIR, PS_FST_VTYPE_VDIR },
1635                 { VFIFO, PS_FST_VTYPE_VFIFO },
1636                 { VLNK, PS_FST_VTYPE_VLNK },
1637                 { VNON, PS_FST_VTYPE_VNON },
1638                 { VREG, PS_FST_VTYPE_VREG },
1639                 { VSOCK, PS_FST_VTYPE_VSOCK }
1640         };
1641 #define NVFTYPES        (sizeof(vt2fst) / sizeof(*vt2fst))
1642         unsigned int i, fst_type;
1643
1644         fst_type = PS_FST_VTYPE_UNKNOWN;
1645         for (i = 0; i < NVFTYPES; i++) {
1646                 if (type == vt2fst[i].vtype) {
1647                         fst_type = vt2fst[i].fst_vtype;
1648                         break;
1649                 }
1650         }
1651         return (fst_type);
1652 }
1653
1654 static char *
1655 getmnton(kvm_t *kd, struct mount *m)
1656 {
1657         struct mount mnt;
1658         static struct mtab {
1659                 struct mtab *next;
1660                 struct mount *m;
1661                 char mntonname[MNAMELEN + 1];
1662         } *mhead = NULL;
1663         struct mtab *mt;
1664
1665         for (mt = mhead; mt != NULL; mt = mt->next)
1666                 if (m == mt->m)
1667                         return (mt->mntonname);
1668         if (!kvm_read_all(kd, (unsigned long)m, &mnt, sizeof(struct mount))) {
1669                 warnx("can't read mount table at %p", (void *)m);
1670                 return (NULL);
1671         }
1672         if ((mt = malloc(sizeof (struct mtab))) == NULL)
1673                 err(1, NULL);
1674         mt->m = m;
1675         bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
1676         mt->mntonname[MNAMELEN] = '\0';
1677         mt->next = mhead;
1678         mhead = mt;
1679         return (mt->mntonname);
1680 }
1681
1682 /*
1683  * Auxiliary structures and functions to get process environment or
1684  * command line arguments.
1685  */
1686 struct argvec {
1687         char    *buf;
1688         size_t  bufsize;
1689         char    **argv;
1690         size_t  argc;
1691 };
1692
1693 static struct argvec *
1694 argvec_alloc(size_t bufsize)
1695 {
1696         struct argvec *av;
1697
1698         av = malloc(sizeof(*av));
1699         if (av == NULL)
1700                 return (NULL);
1701         av->bufsize = bufsize;
1702         av->buf = malloc(av->bufsize);
1703         if (av->buf == NULL) {
1704                 free(av);
1705                 return (NULL);
1706         }
1707         av->argc = 32;
1708         av->argv = malloc(sizeof(char *) * av->argc);
1709         if (av->argv == NULL) {
1710                 free(av->buf);
1711                 free(av);
1712                 return (NULL);
1713         }
1714         return av;
1715 }
1716
1717 static void
1718 argvec_free(struct argvec * av)
1719 {
1720
1721         free(av->argv);
1722         free(av->buf);
1723         free(av);
1724 }
1725
1726 static char **
1727 getargv(struct procstat *procstat, struct kinfo_proc *kp, size_t nchr, int env)
1728 {
1729         int error, name[4], argc, i;
1730         struct argvec *av, **avp;
1731         enum psc_type type;
1732         size_t len;
1733         char *p, **argv;
1734
1735         assert(procstat);
1736         assert(kp);
1737         if (procstat->type == PROCSTAT_KVM) {
1738                 warnx("can't use kvm access method");
1739                 return (NULL);
1740         }
1741         if (procstat->type != PROCSTAT_SYSCTL &&
1742             procstat->type != PROCSTAT_CORE) {
1743                 warnx("unknown access method: %d", procstat->type);
1744                 return (NULL);
1745         }
1746
1747         if (nchr == 0 || nchr > ARG_MAX)
1748                 nchr = ARG_MAX;
1749
1750         avp = (struct argvec **)(env ? &procstat->argv : &procstat->envv);
1751         av = *avp;
1752
1753         if (av == NULL)
1754         {
1755                 av = argvec_alloc(nchr);
1756                 if (av == NULL)
1757                 {
1758                         warn("malloc(%zu)", nchr);
1759                         return (NULL);
1760                 }
1761                 *avp = av;
1762         } else if (av->bufsize < nchr) {
1763                 av->buf = reallocf(av->buf, nchr);
1764                 if (av->buf == NULL) {
1765                         warn("malloc(%zu)", nchr);
1766                         return (NULL);
1767                 }
1768         }
1769         if (procstat->type == PROCSTAT_SYSCTL) {
1770                 name[0] = CTL_KERN;
1771                 name[1] = KERN_PROC;
1772                 name[2] = env ? KERN_PROC_ENV : KERN_PROC_ARGS;
1773                 name[3] = kp->ki_pid;
1774                 len = nchr;
1775                 error = sysctl(name, nitems(name), av->buf, &len, NULL, 0);
1776                 if (error != 0 && errno != ESRCH && errno != EPERM)
1777                         warn("sysctl(kern.proc.%s)", env ? "env" : "args");
1778                 if (error != 0 || len == 0)
1779                         return (NULL);
1780         } else /* procstat->type == PROCSTAT_CORE */ {
1781                 type = env ? PSC_TYPE_ENVV : PSC_TYPE_ARGV;
1782                 len = nchr;
1783                 if (procstat_core_get(procstat->core, type, av->buf, &len)
1784                     == NULL) {
1785                         return (NULL);
1786                 }
1787         }
1788
1789         argv = av->argv;
1790         argc = av->argc;
1791         i = 0;
1792         for (p = av->buf; p < av->buf + len; p += strlen(p) + 1) {
1793                 argv[i++] = p;
1794                 if (i < argc)
1795                         continue;
1796                 /* Grow argv. */
1797                 argc += argc;
1798                 argv = realloc(argv, sizeof(char *) * argc);
1799                 if (argv == NULL) {
1800                         warn("malloc(%zu)", sizeof(char *) * argc);
1801                         return (NULL);
1802                 }
1803                 av->argv = argv;
1804                 av->argc = argc;
1805         }
1806         argv[i] = NULL;
1807
1808         return (argv);
1809 }
1810
1811 /*
1812  * Return process command line arguments.
1813  */
1814 char **
1815 procstat_getargv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr)
1816 {
1817
1818         return (getargv(procstat, p, nchr, 0));
1819 }
1820
1821 /*
1822  * Free the buffer allocated by procstat_getargv().
1823  */
1824 void
1825 procstat_freeargv(struct procstat *procstat)
1826 {
1827
1828         if (procstat->argv != NULL) {
1829                 argvec_free(procstat->argv);
1830                 procstat->argv = NULL;
1831         }
1832 }
1833
1834 /*
1835  * Return process environment.
1836  */
1837 char **
1838 procstat_getenvv(struct procstat *procstat, struct kinfo_proc *p, size_t nchr)
1839 {
1840
1841         return (getargv(procstat, p, nchr, 1));
1842 }
1843
1844 /*
1845  * Free the buffer allocated by procstat_getenvv().
1846  */
1847 void
1848 procstat_freeenvv(struct procstat *procstat)
1849 {
1850         if (procstat->envv != NULL) {
1851                 argvec_free(procstat->envv);
1852                 procstat->envv = NULL;
1853         }
1854 }
1855
1856 static struct kinfo_vmentry *
1857 kinfo_getvmmap_core(struct procstat_core *core, int *cntp)
1858 {
1859         int cnt;
1860         size_t len;
1861         char *buf, *bp, *eb;
1862         struct kinfo_vmentry *kiv, *kp, *kv;
1863
1864         buf = procstat_core_get(core, PSC_TYPE_VMMAP, NULL, &len);
1865         if (buf == NULL)
1866                 return (NULL);
1867
1868         /*
1869          * XXXMG: The code below is just copy&past from libutil.
1870          * The code duplication can be avoided if libutil
1871          * is extended to provide something like:
1872          *   struct kinfo_vmentry *kinfo_getvmmap_from_buf(const char *buf,
1873          *       size_t len, int *cntp);
1874          */
1875
1876         /* Pass 1: count items */
1877         cnt = 0;
1878         bp = buf;
1879         eb = buf + len;
1880         while (bp < eb) {
1881                 kv = (struct kinfo_vmentry *)(uintptr_t)bp;
1882                 if (kv->kve_structsize == 0)
1883                         break;
1884                 bp += kv->kve_structsize;
1885                 cnt++;
1886         }
1887
1888         kiv = calloc(cnt, sizeof(*kiv));
1889         if (kiv == NULL) {
1890                 free(buf);
1891                 return (NULL);
1892         }
1893         bp = buf;
1894         eb = buf + len;
1895         kp = kiv;
1896         /* Pass 2: unpack */
1897         while (bp < eb) {
1898                 kv = (struct kinfo_vmentry *)(uintptr_t)bp;
1899                 if (kv->kve_structsize == 0)
1900                         break;
1901                 /* Copy/expand into pre-zeroed buffer */
1902                 memcpy(kp, kv, kv->kve_structsize);
1903                 /* Advance to next packed record */
1904                 bp += kv->kve_structsize;
1905                 /* Set field size to fixed length, advance */
1906                 kp->kve_structsize = sizeof(*kp);
1907                 kp++;
1908         }
1909         free(buf);
1910         *cntp = cnt;
1911         return (kiv);   /* Caller must free() return value */
1912 }
1913
1914 struct kinfo_vmentry *
1915 procstat_getvmmap(struct procstat *procstat, struct kinfo_proc *kp,
1916     unsigned int *cntp)
1917 {
1918
1919         switch(procstat->type) {
1920         case PROCSTAT_KVM:
1921                 warnx("kvm method is not supported");
1922                 return (NULL);
1923         case PROCSTAT_SYSCTL:
1924                 return (kinfo_getvmmap(kp->ki_pid, cntp));
1925         case PROCSTAT_CORE:
1926                 return (kinfo_getvmmap_core(procstat->core, cntp));
1927         default:
1928                 warnx("unknown access method: %d", procstat->type);
1929                 return (NULL);
1930         }
1931 }
1932
1933 void
1934 procstat_freevmmap(struct procstat *procstat __unused,
1935     struct kinfo_vmentry *vmmap)
1936 {
1937
1938         free(vmmap);
1939 }
1940
1941 static gid_t *
1942 procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp)
1943 {
1944         struct proc proc;
1945         struct ucred ucred;
1946         gid_t *groups;
1947         size_t len;
1948
1949         assert(kd != NULL);
1950         assert(kp != NULL);
1951         if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
1952             sizeof(proc))) {
1953                 warnx("can't read proc struct at %p for pid %d",
1954                     kp->ki_paddr, kp->ki_pid);
1955                 return (NULL);
1956         }
1957         if (proc.p_ucred == NOCRED)
1958                 return (NULL);
1959         if (!kvm_read_all(kd, (unsigned long)proc.p_ucred, &ucred,
1960             sizeof(ucred))) {
1961                 warnx("can't read ucred struct at %p for pid %d",
1962                     proc.p_ucred, kp->ki_pid);
1963                 return (NULL);
1964         }
1965         len = ucred.cr_ngroups * sizeof(gid_t);
1966         groups = malloc(len);
1967         if (groups == NULL) {
1968                 warn("malloc(%zu)", len);
1969                 return (NULL);
1970         }
1971         if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups, len)) {
1972                 warnx("can't read groups at %p for pid %d",
1973                     ucred.cr_groups, kp->ki_pid);
1974                 free(groups);
1975                 return (NULL);
1976         }
1977         *cntp = ucred.cr_ngroups;
1978         return (groups);
1979 }
1980
1981 static gid_t *
1982 procstat_getgroups_sysctl(pid_t pid, unsigned int *cntp)
1983 {
1984         int mib[4];
1985         size_t len;
1986         gid_t *groups;
1987
1988         mib[0] = CTL_KERN;
1989         mib[1] = KERN_PROC;
1990         mib[2] = KERN_PROC_GROUPS;
1991         mib[3] = pid;
1992         len = (sysconf(_SC_NGROUPS_MAX) + 1) * sizeof(gid_t);
1993         groups = malloc(len);
1994         if (groups == NULL) {
1995                 warn("malloc(%zu)", len);
1996                 return (NULL);
1997         }
1998         if (sysctl(mib, nitems(mib), groups, &len, NULL, 0) == -1) {
1999                 warn("sysctl: kern.proc.groups: %d", pid);
2000                 free(groups);
2001                 return (NULL);
2002         }
2003         *cntp = len / sizeof(gid_t);
2004         return (groups);
2005 }
2006
2007 static gid_t *
2008 procstat_getgroups_core(struct procstat_core *core, unsigned int *cntp)
2009 {
2010         size_t len;
2011         gid_t *groups;
2012
2013         groups = procstat_core_get(core, PSC_TYPE_GROUPS, NULL, &len);
2014         if (groups == NULL)
2015                 return (NULL);
2016         *cntp = len / sizeof(gid_t);
2017         return (groups);
2018 }
2019
2020 gid_t *
2021 procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp,
2022     unsigned int *cntp)
2023 {
2024         switch(procstat->type) {
2025         case PROCSTAT_KVM:
2026                 return (procstat_getgroups_kvm(procstat->kd, kp, cntp));
2027         case PROCSTAT_SYSCTL:
2028                 return (procstat_getgroups_sysctl(kp->ki_pid, cntp));
2029         case PROCSTAT_CORE:
2030                 return (procstat_getgroups_core(procstat->core, cntp));
2031         default:
2032                 warnx("unknown access method: %d", procstat->type);
2033                 return (NULL);
2034         }
2035 }
2036
2037 void
2038 procstat_freegroups(struct procstat *procstat __unused, gid_t *groups)
2039 {
2040
2041         free(groups);
2042 }
2043
2044 static int
2045 procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned short *maskp)
2046 {
2047         struct filedesc fd;
2048
2049         assert(kd != NULL);
2050         assert(kp != NULL);
2051         if (kp->ki_fd == NULL)
2052                 return (-1);
2053         if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &fd, sizeof(fd))) {
2054                 warnx("can't read filedesc at %p for pid %d", kp->ki_fd,
2055                     kp->ki_pid);
2056                 return (-1);
2057         }
2058         *maskp = fd.fd_cmask;
2059         return (0);
2060 }
2061
2062 static int
2063 procstat_getumask_sysctl(pid_t pid, unsigned short *maskp)
2064 {
2065         int error;
2066         int mib[4];
2067         size_t len;
2068
2069         mib[0] = CTL_KERN;
2070         mib[1] = KERN_PROC;
2071         mib[2] = KERN_PROC_UMASK;
2072         mib[3] = pid;
2073         len = sizeof(*maskp);
2074         error = sysctl(mib, nitems(mib), maskp, &len, NULL, 0);
2075         if (error != 0 && errno != ESRCH && errno != EPERM)
2076                 warn("sysctl: kern.proc.umask: %d", pid);
2077         return (error);
2078 }
2079
2080 static int
2081 procstat_getumask_core(struct procstat_core *core, unsigned short *maskp)
2082 {
2083         size_t len;
2084         unsigned short *buf;
2085
2086         buf = procstat_core_get(core, PSC_TYPE_UMASK, NULL, &len);
2087         if (buf == NULL)
2088                 return (-1);
2089         if (len < sizeof(*maskp)) {
2090                 free(buf);
2091                 return (-1);
2092         }
2093         *maskp = *buf;
2094         free(buf);
2095         return (0);
2096 }
2097
2098 int
2099 procstat_getumask(struct procstat *procstat, struct kinfo_proc *kp,
2100     unsigned short *maskp)
2101 {
2102         switch(procstat->type) {
2103         case PROCSTAT_KVM:
2104                 return (procstat_getumask_kvm(procstat->kd, kp, maskp));
2105         case PROCSTAT_SYSCTL:
2106                 return (procstat_getumask_sysctl(kp->ki_pid, maskp));
2107         case PROCSTAT_CORE:
2108                 return (procstat_getumask_core(procstat->core, maskp));
2109         default:
2110                 warnx("unknown access method: %d", procstat->type);
2111                 return (-1);
2112         }
2113 }
2114
2115 static int
2116 procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp, int which,
2117     struct rlimit* rlimit)
2118 {
2119         struct proc proc;
2120         unsigned long offset;
2121
2122         assert(kd != NULL);
2123         assert(kp != NULL);
2124         assert(which >= 0 && which < RLIM_NLIMITS);
2125         if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
2126             sizeof(proc))) {
2127                 warnx("can't read proc struct at %p for pid %d",
2128                     kp->ki_paddr, kp->ki_pid);
2129                 return (-1);
2130         }
2131         if (proc.p_limit == NULL)
2132                 return (-1);
2133         offset = (unsigned long)proc.p_limit + sizeof(struct rlimit) * which;
2134         if (!kvm_read_all(kd, offset, rlimit, sizeof(*rlimit))) {
2135                 warnx("can't read rlimit struct at %p for pid %d",
2136                     (void *)offset, kp->ki_pid);
2137                 return (-1);
2138         }
2139         return (0);
2140 }
2141
2142 static int
2143 procstat_getrlimit_sysctl(pid_t pid, int which, struct rlimit* rlimit)
2144 {
2145         int error, name[5];
2146         size_t len;
2147
2148         name[0] = CTL_KERN;
2149         name[1] = KERN_PROC;
2150         name[2] = KERN_PROC_RLIMIT;
2151         name[3] = pid;
2152         name[4] = which;
2153         len = sizeof(struct rlimit);
2154         error = sysctl(name, nitems(name), rlimit, &len, NULL, 0);
2155         if (error < 0 && errno != ESRCH) {
2156                 warn("sysctl: kern.proc.rlimit: %d", pid);
2157                 return (-1);
2158         }
2159         if (error < 0 || len != sizeof(struct rlimit))
2160                 return (-1);
2161         return (0);
2162 }
2163
2164 static int
2165 procstat_getrlimit_core(struct procstat_core *core, int which,
2166     struct rlimit* rlimit)
2167 {
2168         size_t len;
2169         struct rlimit* rlimits;
2170
2171         if (which < 0 || which >= RLIM_NLIMITS) {
2172                 errno = EINVAL;
2173                 warn("getrlimit: which");
2174                 return (-1);
2175         }
2176         rlimits = procstat_core_get(core, PSC_TYPE_RLIMIT, NULL, &len);
2177         if (rlimits == NULL)
2178                 return (-1);
2179         if (len < sizeof(struct rlimit) * RLIM_NLIMITS) {
2180                 free(rlimits);
2181                 return (-1);
2182         }
2183         *rlimit = rlimits[which];
2184         return (0);
2185 }
2186
2187 int
2188 procstat_getrlimit(struct procstat *procstat, struct kinfo_proc *kp, int which,
2189     struct rlimit* rlimit)
2190 {
2191         switch(procstat->type) {
2192         case PROCSTAT_KVM:
2193                 return (procstat_getrlimit_kvm(procstat->kd, kp, which,
2194                     rlimit));
2195         case PROCSTAT_SYSCTL:
2196                 return (procstat_getrlimit_sysctl(kp->ki_pid, which, rlimit));
2197         case PROCSTAT_CORE:
2198                 return (procstat_getrlimit_core(procstat->core, which, rlimit));
2199         default:
2200                 warnx("unknown access method: %d", procstat->type);
2201                 return (-1);
2202         }
2203 }
2204
2205 static int
2206 procstat_getpathname_sysctl(pid_t pid, char *pathname, size_t maxlen)
2207 {
2208         int error, name[4];
2209         size_t len;
2210
2211         name[0] = CTL_KERN;
2212         name[1] = KERN_PROC;
2213         name[2] = KERN_PROC_PATHNAME;
2214         name[3] = pid;
2215         len = maxlen;
2216         error = sysctl(name, nitems(name), pathname, &len, NULL, 0);
2217         if (error != 0 && errno != ESRCH)
2218                 warn("sysctl: kern.proc.pathname: %d", pid);
2219         if (len == 0)
2220                 pathname[0] = '\0';
2221         return (error);
2222 }
2223
2224 static int
2225 procstat_getpathname_core(struct procstat_core *core, char *pathname,
2226     size_t maxlen)
2227 {
2228         struct kinfo_file *files;
2229         int cnt, i, result;
2230
2231         files = kinfo_getfile_core(core, &cnt);
2232         if (files == NULL)
2233                 return (-1);
2234         result = -1;
2235         for (i = 0; i < cnt; i++) {
2236                 if (files[i].kf_fd != KF_FD_TYPE_TEXT)
2237                         continue;
2238                 strncpy(pathname, files[i].kf_path, maxlen);
2239                 result = 0;
2240                 break;
2241         }
2242         free(files);
2243         return (result);
2244 }
2245
2246 int
2247 procstat_getpathname(struct procstat *procstat, struct kinfo_proc *kp,
2248     char *pathname, size_t maxlen)
2249 {
2250         switch(procstat->type) {
2251         case PROCSTAT_KVM:
2252                 /* XXX: Return empty string. */
2253                 if (maxlen > 0)
2254                         pathname[0] = '\0';
2255                 return (0);
2256         case PROCSTAT_SYSCTL:
2257                 return (procstat_getpathname_sysctl(kp->ki_pid, pathname,
2258                     maxlen));
2259         case PROCSTAT_CORE:
2260                 return (procstat_getpathname_core(procstat->core, pathname,
2261                     maxlen));
2262         default:
2263                 warnx("unknown access method: %d", procstat->type);
2264                 return (-1);
2265         }
2266 }
2267
2268 static int
2269 procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp, int *osrelp)
2270 {
2271         struct proc proc;
2272
2273         assert(kd != NULL);
2274         assert(kp != NULL);
2275         if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
2276             sizeof(proc))) {
2277                 warnx("can't read proc struct at %p for pid %d",
2278                     kp->ki_paddr, kp->ki_pid);
2279                 return (-1);
2280         }
2281         *osrelp = proc.p_osrel;
2282         return (0);
2283 }
2284
2285 static int
2286 procstat_getosrel_sysctl(pid_t pid, int *osrelp)
2287 {
2288         int error, name[4];
2289         size_t len;
2290
2291         name[0] = CTL_KERN;
2292         name[1] = KERN_PROC;
2293         name[2] = KERN_PROC_OSREL;
2294         name[3] = pid;
2295         len = sizeof(*osrelp);
2296         error = sysctl(name, nitems(name), osrelp, &len, NULL, 0);
2297         if (error != 0 && errno != ESRCH)
2298                 warn("sysctl: kern.proc.osrel: %d", pid);
2299         return (error);
2300 }
2301
2302 static int
2303 procstat_getosrel_core(struct procstat_core *core, int *osrelp)
2304 {
2305         size_t len;
2306         int *buf;
2307
2308         buf = procstat_core_get(core, PSC_TYPE_OSREL, NULL, &len);
2309         if (buf == NULL)
2310                 return (-1);
2311         if (len < sizeof(*osrelp)) {
2312                 free(buf);
2313                 return (-1);
2314         }
2315         *osrelp = *buf;
2316         free(buf);
2317         return (0);
2318 }
2319
2320 int
2321 procstat_getosrel(struct procstat *procstat, struct kinfo_proc *kp, int *osrelp)
2322 {
2323         switch(procstat->type) {
2324         case PROCSTAT_KVM:
2325                 return (procstat_getosrel_kvm(procstat->kd, kp, osrelp));
2326         case PROCSTAT_SYSCTL:
2327                 return (procstat_getosrel_sysctl(kp->ki_pid, osrelp));
2328         case PROCSTAT_CORE:
2329                 return (procstat_getosrel_core(procstat->core, osrelp));
2330         default:
2331                 warnx("unknown access method: %d", procstat->type);
2332                 return (-1);
2333         }
2334 }
2335
2336 #define PROC_AUXV_MAX   256
2337
2338 #if __ELF_WORD_SIZE == 64
2339 static const char *elf32_sv_names[] = {
2340         "Linux ELF32",
2341         "FreeBSD ELF32",
2342 };
2343
2344 static int
2345 is_elf32_sysctl(pid_t pid)
2346 {
2347         int error, name[4];
2348         size_t len, i;
2349         static char sv_name[256];
2350
2351         name[0] = CTL_KERN;
2352         name[1] = KERN_PROC;
2353         name[2] = KERN_PROC_SV_NAME;
2354         name[3] = pid;
2355         len = sizeof(sv_name);
2356         error = sysctl(name, nitems(name), sv_name, &len, NULL, 0);
2357         if (error != 0 || len == 0)
2358                 return (0);
2359         for (i = 0; i < sizeof(elf32_sv_names) / sizeof(*elf32_sv_names); i++) {
2360                 if (strncmp(sv_name, elf32_sv_names[i], sizeof(sv_name)) == 0)
2361                         return (1);
2362         }
2363         return (0);
2364 }
2365
2366 static Elf_Auxinfo *
2367 procstat_getauxv32_sysctl(pid_t pid, unsigned int *cntp)
2368 {
2369         Elf_Auxinfo *auxv;
2370         Elf32_Auxinfo *auxv32;
2371         void *ptr;
2372         size_t len;
2373         unsigned int i, count;
2374         int name[4];
2375
2376         name[0] = CTL_KERN;
2377         name[1] = KERN_PROC;
2378         name[2] = KERN_PROC_AUXV;
2379         name[3] = pid;
2380         len = PROC_AUXV_MAX * sizeof(Elf32_Auxinfo);
2381         auxv = NULL;
2382         auxv32 = malloc(len);
2383         if (auxv32 == NULL) {
2384                 warn("malloc(%zu)", len);
2385                 goto out;
2386         }
2387         if (sysctl(name, nitems(name), auxv32, &len, NULL, 0) == -1) {
2388                 if (errno != ESRCH && errno != EPERM)
2389                         warn("sysctl: kern.proc.auxv: %d: %d", pid, errno);
2390                 goto out;
2391         }
2392         count = len / sizeof(Elf_Auxinfo);
2393         auxv = malloc(count  * sizeof(Elf_Auxinfo));
2394         if (auxv == NULL) {
2395                 warn("malloc(%zu)", count * sizeof(Elf_Auxinfo));
2396                 goto out;
2397         }
2398         for (i = 0; i < count; i++) {
2399                 /*
2400                  * XXX: We expect that values for a_type on a 32-bit platform
2401                  * are directly mapped to values on 64-bit one, which is not
2402                  * necessarily true.
2403                  */
2404                 auxv[i].a_type = auxv32[i].a_type;
2405                 ptr = &auxv32[i].a_un;
2406                 auxv[i].a_un.a_val = *((uint32_t *)ptr);
2407         }
2408         *cntp = count;
2409 out:
2410         free(auxv32);
2411         return (auxv);
2412 }
2413 #endif /* __ELF_WORD_SIZE == 64 */
2414
2415 static Elf_Auxinfo *
2416 procstat_getauxv_sysctl(pid_t pid, unsigned int *cntp)
2417 {
2418         Elf_Auxinfo *auxv;
2419         int name[4];
2420         size_t len;
2421
2422 #if __ELF_WORD_SIZE == 64
2423         if (is_elf32_sysctl(pid))
2424                 return (procstat_getauxv32_sysctl(pid, cntp));
2425 #endif
2426         name[0] = CTL_KERN;
2427         name[1] = KERN_PROC;
2428         name[2] = KERN_PROC_AUXV;
2429         name[3] = pid;
2430         len = PROC_AUXV_MAX * sizeof(Elf_Auxinfo);
2431         auxv = malloc(len);
2432         if (auxv == NULL) {
2433                 warn("malloc(%zu)", len);
2434                 return (NULL);
2435         }
2436         if (sysctl(name, nitems(name), auxv, &len, NULL, 0) == -1) {
2437                 if (errno != ESRCH && errno != EPERM)
2438                         warn("sysctl: kern.proc.auxv: %d: %d", pid, errno);
2439                 free(auxv);
2440                 return (NULL);
2441         }
2442         *cntp = len / sizeof(Elf_Auxinfo);
2443         return (auxv);
2444 }
2445
2446 static Elf_Auxinfo *
2447 procstat_getauxv_core(struct procstat_core *core, unsigned int *cntp)
2448 {
2449         Elf_Auxinfo *auxv;
2450         size_t len;
2451
2452         auxv = procstat_core_get(core, PSC_TYPE_AUXV, NULL, &len);
2453         if (auxv == NULL)
2454                 return (NULL);
2455         *cntp = len / sizeof(Elf_Auxinfo);
2456         return (auxv);
2457 }
2458
2459 Elf_Auxinfo *
2460 procstat_getauxv(struct procstat *procstat, struct kinfo_proc *kp,
2461     unsigned int *cntp)
2462 {
2463         switch(procstat->type) {
2464         case PROCSTAT_KVM:
2465                 warnx("kvm method is not supported");
2466                 return (NULL);
2467         case PROCSTAT_SYSCTL:
2468                 return (procstat_getauxv_sysctl(kp->ki_pid, cntp));
2469         case PROCSTAT_CORE:
2470                 return (procstat_getauxv_core(procstat->core, cntp));
2471         default:
2472                 warnx("unknown access method: %d", procstat->type);
2473                 return (NULL);
2474         }
2475 }
2476
2477 void
2478 procstat_freeauxv(struct procstat *procstat __unused, Elf_Auxinfo *auxv)
2479 {
2480
2481         free(auxv);
2482 }
2483
2484 static struct ptrace_lwpinfo *
2485 procstat_getptlwpinfo_core(struct procstat_core *core, unsigned int *cntp)
2486 {
2487         void *buf;
2488         struct ptrace_lwpinfo *pl;
2489         unsigned int cnt;
2490         size_t len;
2491
2492         cnt = procstat_core_note_count(core, PSC_TYPE_PTLWPINFO);
2493         if (cnt == 0)
2494                 return (NULL);
2495
2496         len = cnt * sizeof(*pl);
2497         buf = calloc(1, len);
2498         pl = procstat_core_get(core, PSC_TYPE_PTLWPINFO, buf, &len);
2499         if (pl == NULL) {
2500                 free(buf);
2501                 return (NULL);
2502         }
2503         *cntp = len / sizeof(*pl);
2504         return (pl);
2505 }
2506
2507 struct ptrace_lwpinfo *
2508 procstat_getptlwpinfo(struct procstat *procstat, unsigned int *cntp)
2509 {
2510         switch (procstat->type) {
2511         case PROCSTAT_CORE:
2512                 return (procstat_getptlwpinfo_core(procstat->core, cntp));
2513         default:
2514                 warnx("unknown access method: %d", procstat->type);
2515                 return (NULL);
2516         }
2517 }
2518
2519 void
2520 procstat_freeptlwpinfo(struct procstat *procstat __unused,
2521     struct ptrace_lwpinfo *pl)
2522 {
2523         free(pl);
2524 }
2525
2526 static struct kinfo_kstack *
2527 procstat_getkstack_sysctl(pid_t pid, int *cntp)
2528 {
2529         struct kinfo_kstack *kkstp;
2530         int error, name[4];
2531         size_t len;
2532
2533         name[0] = CTL_KERN;
2534         name[1] = KERN_PROC;
2535         name[2] = KERN_PROC_KSTACK;
2536         name[3] = pid;
2537
2538         len = 0;
2539         error = sysctl(name, nitems(name), NULL, &len, NULL, 0);
2540         if (error < 0 && errno != ESRCH && errno != EPERM && errno != ENOENT) {
2541                 warn("sysctl: kern.proc.kstack: %d", pid);
2542                 return (NULL);
2543         }
2544         if (error == -1 && errno == ENOENT) {
2545                 warnx("sysctl: kern.proc.kstack unavailable"
2546                     " (options DDB or options STACK required in kernel)");
2547                 return (NULL);
2548         }
2549         if (error == -1)
2550                 return (NULL);
2551         kkstp = malloc(len);
2552         if (kkstp == NULL) {
2553                 warn("malloc(%zu)", len);
2554                 return (NULL);
2555         }
2556         if (sysctl(name, nitems(name), kkstp, &len, NULL, 0) == -1) {
2557                 warn("sysctl: kern.proc.pid: %d", pid);
2558                 free(kkstp);
2559                 return (NULL);
2560         }
2561         *cntp = len / sizeof(*kkstp);
2562
2563         return (kkstp);
2564 }
2565
2566 struct kinfo_kstack *
2567 procstat_getkstack(struct procstat *procstat, struct kinfo_proc *kp,
2568     unsigned int *cntp)
2569 {
2570         switch(procstat->type) {
2571         case PROCSTAT_KVM:
2572                 warnx("kvm method is not supported");
2573                 return (NULL);
2574         case PROCSTAT_SYSCTL:
2575                 return (procstat_getkstack_sysctl(kp->ki_pid, cntp));
2576         case PROCSTAT_CORE:
2577                 warnx("core method is not supported");
2578                 return (NULL);
2579         default:
2580                 warnx("unknown access method: %d", procstat->type);
2581                 return (NULL);
2582         }
2583 }
2584
2585 void
2586 procstat_freekstack(struct procstat *procstat __unused,
2587     struct kinfo_kstack *kkstp)
2588 {
2589
2590         free(kkstp);
2591 }