1*0daf62d9SStanislav Sedov /*-
2*0daf62d9SStanislav Sedov  * Copyright (c) 2009 Stanislav Sedov <[email protected]>
3*0daf62d9SStanislav Sedov  * Copyright (c) 1988, 1993
4*0daf62d9SStanislav Sedov  *      The Regents of the University of California.  All rights reserved.
5*0daf62d9SStanislav Sedov  *
6*0daf62d9SStanislav Sedov  * Redistribution and use in source and binary forms, with or without
7*0daf62d9SStanislav Sedov  * modification, are permitted provided that the following conditions
8*0daf62d9SStanislav Sedov  * are met:
9*0daf62d9SStanislav Sedov  * 1. Redistributions of source code must retain the above copyright
10*0daf62d9SStanislav Sedov  *    notice, this list of conditions and the following disclaimer.
11*0daf62d9SStanislav Sedov  * 2. Redistributions in binary form must reproduce the above copyright
12*0daf62d9SStanislav Sedov  *    notice, this list of conditions and the following disclaimer in the
13*0daf62d9SStanislav Sedov  *    documentation and/or other materials provided with the distribution.
14*0daf62d9SStanislav Sedov  * 3. All advertising materials mentioning features or use of this software
15*0daf62d9SStanislav Sedov  *    must display the following acknowledgement:
16*0daf62d9SStanislav Sedov  *      This product includes software developed by the University of
17*0daf62d9SStanislav Sedov  *      California, Berkeley and its contributors.
18*0daf62d9SStanislav Sedov  * 4. Neither the name of the University nor the names of its contributors
19*0daf62d9SStanislav Sedov  *    may be used to endorse or promote products derived from this software
20*0daf62d9SStanislav Sedov  *    without specific prior written permission.
21*0daf62d9SStanislav Sedov  *
22*0daf62d9SStanislav Sedov  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*0daf62d9SStanislav Sedov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*0daf62d9SStanislav Sedov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*0daf62d9SStanislav Sedov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*0daf62d9SStanislav Sedov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*0daf62d9SStanislav Sedov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*0daf62d9SStanislav Sedov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*0daf62d9SStanislav Sedov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*0daf62d9SStanislav Sedov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*0daf62d9SStanislav Sedov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*0daf62d9SStanislav Sedov  * SUCH DAMAGE.
33*0daf62d9SStanislav Sedov  */
34*0daf62d9SStanislav Sedov 
35*0daf62d9SStanislav Sedov #include <sys/cdefs.h>
36*0daf62d9SStanislav Sedov __FBSDID("$FreeBSD$");
37*0daf62d9SStanislav Sedov 
38*0daf62d9SStanislav Sedov #include <sys/param.h>
39*0daf62d9SStanislav Sedov #include <sys/time.h>
40*0daf62d9SStanislav Sedov #include <sys/proc.h>
41*0daf62d9SStanislav Sedov #include <sys/user.h>
42*0daf62d9SStanislav Sedov #include <sys/stat.h>
43*0daf62d9SStanislav Sedov #include <sys/vnode.h>
44*0daf62d9SStanislav Sedov #include <sys/socket.h>
45*0daf62d9SStanislav Sedov #include <sys/socketvar.h>
46*0daf62d9SStanislav Sedov #include <sys/domain.h>
47*0daf62d9SStanislav Sedov #include <sys/protosw.h>
48*0daf62d9SStanislav Sedov #include <sys/un.h>
49*0daf62d9SStanislav Sedov #include <sys/unpcb.h>
50*0daf62d9SStanislav Sedov #include <sys/sysctl.h>
51*0daf62d9SStanislav Sedov #include <sys/tty.h>
52*0daf62d9SStanislav Sedov #include <sys/filedesc.h>
53*0daf62d9SStanislav Sedov #include <sys/queue.h>
54*0daf62d9SStanislav Sedov #define	_WANT_FILE
55*0daf62d9SStanislav Sedov #include <sys/file.h>
56*0daf62d9SStanislav Sedov #include <sys/conf.h>
57*0daf62d9SStanislav Sedov #define	_KERNEL
58*0daf62d9SStanislav Sedov #include <sys/mount.h>
59*0daf62d9SStanislav Sedov #include <sys/pipe.h>
60*0daf62d9SStanislav Sedov #include <ufs/ufs/quota.h>
61*0daf62d9SStanislav Sedov #include <ufs/ufs/inode.h>
62*0daf62d9SStanislav Sedov #include <fs/devfs/devfs.h>
63*0daf62d9SStanislav Sedov #include <fs/devfs/devfs_int.h>
64*0daf62d9SStanislav Sedov #undef _KERNEL
65*0daf62d9SStanislav Sedov #include <nfs/nfsproto.h>
66*0daf62d9SStanislav Sedov #include <nfsclient/nfs.h>
67*0daf62d9SStanislav Sedov #include <nfsclient/nfsnode.h>
68*0daf62d9SStanislav Sedov 
69*0daf62d9SStanislav Sedov #include <vm/vm.h>
70*0daf62d9SStanislav Sedov #include <vm/vm_map.h>
71*0daf62d9SStanislav Sedov #include <vm/vm_object.h>
72*0daf62d9SStanislav Sedov 
73*0daf62d9SStanislav Sedov #include <net/route.h>
74*0daf62d9SStanislav Sedov #include <netinet/in.h>
75*0daf62d9SStanislav Sedov #include <netinet/in_systm.h>
76*0daf62d9SStanislav Sedov #include <netinet/ip.h>
77*0daf62d9SStanislav Sedov #include <netinet/in_pcb.h>
78*0daf62d9SStanislav Sedov 
79*0daf62d9SStanislav Sedov #include <assert.h>
80*0daf62d9SStanislav Sedov #include <ctype.h>
81*0daf62d9SStanislav Sedov #include <err.h>
82*0daf62d9SStanislav Sedov #include <fcntl.h>
83*0daf62d9SStanislav Sedov #include <kvm.h>
84*0daf62d9SStanislav Sedov #include <libutil.h>
85*0daf62d9SStanislav Sedov #include <limits.h>
86*0daf62d9SStanislav Sedov #include <paths.h>
87*0daf62d9SStanislav Sedov #include <pwd.h>
88*0daf62d9SStanislav Sedov #include <stdio.h>
89*0daf62d9SStanislav Sedov #include <stdlib.h>
90*0daf62d9SStanislav Sedov #include <stddef.h>
91*0daf62d9SStanislav Sedov #include <string.h>
92*0daf62d9SStanislav Sedov #include <unistd.h>
93*0daf62d9SStanislav Sedov #include <netdb.h>
94*0daf62d9SStanislav Sedov 
95*0daf62d9SStanislav Sedov #include <libprocstat.h>
96*0daf62d9SStanislav Sedov #include "libprocstat_internal.h"
97*0daf62d9SStanislav Sedov #include "common_kvm.h"
98*0daf62d9SStanislav Sedov 
99*0daf62d9SStanislav Sedov int     statfs(const char *, struct statfs *);	/* XXX */
100*0daf62d9SStanislav Sedov 
101*0daf62d9SStanislav Sedov #define	PROCSTAT_KVM	1
102*0daf62d9SStanislav Sedov #define	PROCSTAT_SYSCTL	2
103*0daf62d9SStanislav Sedov 
104*0daf62d9SStanislav Sedov static char	*getmnton(kvm_t *kd, struct mount *m);
105*0daf62d9SStanislav Sedov static struct filestat_list	*procstat_getfiles_kvm(
106*0daf62d9SStanislav Sedov     struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
107*0daf62d9SStanislav Sedov static struct filestat_list	*procstat_getfiles_sysctl(
108*0daf62d9SStanislav Sedov     struct procstat *procstat, struct kinfo_proc *kp, int mmapped);
109*0daf62d9SStanislav Sedov static int	procstat_get_pipe_info_sysctl(struct filestat *fst,
110*0daf62d9SStanislav Sedov     struct pipestat *pipe, char *errbuf);
111*0daf62d9SStanislav Sedov static int	procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst,
112*0daf62d9SStanislav Sedov     struct pipestat *pipe, char *errbuf);
113*0daf62d9SStanislav Sedov static int	procstat_get_pts_info_sysctl(struct filestat *fst,
114*0daf62d9SStanislav Sedov     struct ptsstat *pts, char *errbuf);
115*0daf62d9SStanislav Sedov static int	procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst,
116*0daf62d9SStanislav Sedov     struct ptsstat *pts, char *errbuf);
117*0daf62d9SStanislav Sedov static int	procstat_get_socket_info_sysctl(struct filestat *fst,
118*0daf62d9SStanislav Sedov     struct sockstat *sock, char *errbuf);
119*0daf62d9SStanislav Sedov static int	procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst,
120*0daf62d9SStanislav Sedov     struct sockstat *sock, char *errbuf);
121*0daf62d9SStanislav Sedov static int	to_filestat_flags(int flags);
122*0daf62d9SStanislav Sedov static int	procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
123*0daf62d9SStanislav Sedov     struct vnstat *vn, char *errbuf);
124*0daf62d9SStanislav Sedov static int	procstat_get_vnode_info_sysctl(struct filestat *fst,
125*0daf62d9SStanislav Sedov     struct vnstat *vn, char *errbuf);
126*0daf62d9SStanislav Sedov static int	vntype2psfsttype(int type);
127*0daf62d9SStanislav Sedov 
128*0daf62d9SStanislav Sedov void
129*0daf62d9SStanislav Sedov procstat_close(struct procstat *procstat)
130*0daf62d9SStanislav Sedov {
131*0daf62d9SStanislav Sedov 
132*0daf62d9SStanislav Sedov 	assert(procstat);
133*0daf62d9SStanislav Sedov 	if (procstat->type == PROCSTAT_KVM)
134*0daf62d9SStanislav Sedov 		kvm_close(procstat->kd);
135*0daf62d9SStanislav Sedov }
136*0daf62d9SStanislav Sedov 
137*0daf62d9SStanislav Sedov struct procstat *
138*0daf62d9SStanislav Sedov procstat_open_sysctl(void)
139*0daf62d9SStanislav Sedov {
140*0daf62d9SStanislav Sedov 	struct procstat *procstat;
141*0daf62d9SStanislav Sedov 
142*0daf62d9SStanislav Sedov 	procstat = calloc(1, sizeof(*procstat));
143*0daf62d9SStanislav Sedov 	if (procstat == NULL) {
144*0daf62d9SStanislav Sedov 		warn("malloc()");
145*0daf62d9SStanislav Sedov 		return (NULL);
146*0daf62d9SStanislav Sedov 	}
147*0daf62d9SStanislav Sedov 	procstat->type = PROCSTAT_SYSCTL;
148*0daf62d9SStanislav Sedov 	return (procstat);
149*0daf62d9SStanislav Sedov }
150*0daf62d9SStanislav Sedov 
151*0daf62d9SStanislav Sedov struct procstat *
152*0daf62d9SStanislav Sedov procstat_open_kvm(const char *nlistf, const char *memf)
153*0daf62d9SStanislav Sedov {
154*0daf62d9SStanislav Sedov 	struct procstat *procstat;
155*0daf62d9SStanislav Sedov 	kvm_t *kd;
156*0daf62d9SStanislav Sedov 	char buf[_POSIX2_LINE_MAX];
157*0daf62d9SStanislav Sedov 
158*0daf62d9SStanislav Sedov 	procstat = calloc(1, sizeof(*procstat));
159*0daf62d9SStanislav Sedov 	if (procstat == NULL) {
160*0daf62d9SStanislav Sedov 		warn("malloc()");
161*0daf62d9SStanislav Sedov 		return (NULL);
162*0daf62d9SStanislav Sedov 	}
163*0daf62d9SStanislav Sedov 	kd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
164*0daf62d9SStanislav Sedov 	if (kd == NULL) {
165*0daf62d9SStanislav Sedov 		warnx("kvm_openfiles(): %s", buf);
166*0daf62d9SStanislav Sedov 		free(procstat);
167*0daf62d9SStanislav Sedov 		return (NULL);
168*0daf62d9SStanislav Sedov 	}
169*0daf62d9SStanislav Sedov 	procstat->type = PROCSTAT_KVM;
170*0daf62d9SStanislav Sedov 	procstat->kd = kd;
171*0daf62d9SStanislav Sedov 	return (procstat);
172*0daf62d9SStanislav Sedov }
173*0daf62d9SStanislav Sedov 
174*0daf62d9SStanislav Sedov struct kinfo_proc *
175*0daf62d9SStanislav Sedov procstat_getprocs(struct procstat *procstat, int what, int arg,
176*0daf62d9SStanislav Sedov     unsigned int *count)
177*0daf62d9SStanislav Sedov {
178*0daf62d9SStanislav Sedov 	struct kinfo_proc *p0, *p;
179*0daf62d9SStanislav Sedov 	size_t len;
180*0daf62d9SStanislav Sedov 	int name[4];
181*0daf62d9SStanislav Sedov 	int error;
182*0daf62d9SStanislav Sedov 
183*0daf62d9SStanislav Sedov 	assert(procstat);
184*0daf62d9SStanislav Sedov 	assert(count);
185*0daf62d9SStanislav Sedov 	p = NULL;
186*0daf62d9SStanislav Sedov 	if (procstat->type == PROCSTAT_KVM) {
187*0daf62d9SStanislav Sedov 		p0 = kvm_getprocs(procstat->kd, what, arg, count);
188*0daf62d9SStanislav Sedov 		if (p0 == NULL || count == 0)
189*0daf62d9SStanislav Sedov 			return (NULL);
190*0daf62d9SStanislav Sedov 		len = *count * sizeof(*p);
191*0daf62d9SStanislav Sedov 		p = malloc(len);
192*0daf62d9SStanislav Sedov 		if (p == NULL) {
193*0daf62d9SStanislav Sedov 			warnx("malloc(%zd)", len);
194*0daf62d9SStanislav Sedov 			goto fail;
195*0daf62d9SStanislav Sedov 		}
196*0daf62d9SStanislav Sedov 		bcopy(p0, p, len);
197*0daf62d9SStanislav Sedov 		return (p);
198*0daf62d9SStanislav Sedov 	} else if (procstat->type == PROCSTAT_SYSCTL) {
199*0daf62d9SStanislav Sedov 		len = 0;
200*0daf62d9SStanislav Sedov 		name[0] = CTL_KERN;
201*0daf62d9SStanislav Sedov 		name[1] = KERN_PROC;
202*0daf62d9SStanislav Sedov 		name[2] = what;
203*0daf62d9SStanislav Sedov 		name[3] = arg;
204*0daf62d9SStanislav Sedov 		error = sysctl(name, 4, NULL, &len, NULL, 0);
205*0daf62d9SStanislav Sedov 		if (error < 0 && errno != EPERM) {
206*0daf62d9SStanislav Sedov 			warn("sysctl(kern.proc)");
207*0daf62d9SStanislav Sedov 			goto fail;
208*0daf62d9SStanislav Sedov 		}
209*0daf62d9SStanislav Sedov 		if (len == 0) {
210*0daf62d9SStanislav Sedov 			warnx("no processes?");
211*0daf62d9SStanislav Sedov 			goto fail;
212*0daf62d9SStanislav Sedov 		}
213*0daf62d9SStanislav Sedov 		p = malloc(len);
214*0daf62d9SStanislav Sedov 		if (p == NULL) {
215*0daf62d9SStanislav Sedov 			warnx("malloc(%zd)", len);
216*0daf62d9SStanislav Sedov 			goto fail;
217*0daf62d9SStanislav Sedov 		}
218*0daf62d9SStanislav Sedov 		error = sysctl(name, 4, p, &len, NULL, 0);
219*0daf62d9SStanislav Sedov 		if (error < 0 && errno != EPERM) {
220*0daf62d9SStanislav Sedov 			warn("sysctl(kern.proc)");
221*0daf62d9SStanislav Sedov 			goto fail;
222*0daf62d9SStanislav Sedov 		}
223*0daf62d9SStanislav Sedov 		/* Perform simple consistency checks. */
224*0daf62d9SStanislav Sedov 		if ((len % sizeof(*p)) != 0 || p->ki_structsize != sizeof(*p)) {
225*0daf62d9SStanislav Sedov 			warnx("kinfo_proc structure size mismatch");
226*0daf62d9SStanislav Sedov 			goto fail;
227*0daf62d9SStanislav Sedov 		}
228*0daf62d9SStanislav Sedov 		*count = len / sizeof(*p);
229*0daf62d9SStanislav Sedov 		return (p);
230*0daf62d9SStanislav Sedov 	} else {
231*0daf62d9SStanislav Sedov 		warnx("unknown access method");
232*0daf62d9SStanislav Sedov 		return (NULL);
233*0daf62d9SStanislav Sedov 	}
234*0daf62d9SStanislav Sedov fail:
235*0daf62d9SStanislav Sedov 	if (p)
236*0daf62d9SStanislav Sedov 		free(p);
237*0daf62d9SStanislav Sedov 	return (NULL);
238*0daf62d9SStanislav Sedov }
239*0daf62d9SStanislav Sedov 
240*0daf62d9SStanislav Sedov void
241*0daf62d9SStanislav Sedov procstat_freeprocs(struct procstat *procstat __unused, struct kinfo_proc *p)
242*0daf62d9SStanislav Sedov {
243*0daf62d9SStanislav Sedov 
244*0daf62d9SStanislav Sedov 	if (p != NULL)
245*0daf62d9SStanislav Sedov 		free(p);
246*0daf62d9SStanislav Sedov 	p = NULL;
247*0daf62d9SStanislav Sedov }
248*0daf62d9SStanislav Sedov 
249*0daf62d9SStanislav Sedov struct filestat_list *
250*0daf62d9SStanislav Sedov procstat_getfiles(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
251*0daf62d9SStanislav Sedov {
252*0daf62d9SStanislav Sedov 
253*0daf62d9SStanislav Sedov 	if (procstat->type == PROCSTAT_SYSCTL)
254*0daf62d9SStanislav Sedov 		return (procstat_getfiles_sysctl(procstat, kp, mmapped));
255*0daf62d9SStanislav Sedov 	else if (procstat->type == PROCSTAT_KVM)
256*0daf62d9SStanislav Sedov 		 return (procstat_getfiles_kvm(procstat, kp, mmapped));
257*0daf62d9SStanislav Sedov 	else
258*0daf62d9SStanislav Sedov 		return (NULL);
259*0daf62d9SStanislav Sedov }
260*0daf62d9SStanislav Sedov 
261*0daf62d9SStanislav Sedov void
262*0daf62d9SStanislav Sedov procstat_freefiles(struct procstat *procstat, struct filestat_list *head)
263*0daf62d9SStanislav Sedov {
264*0daf62d9SStanislav Sedov 	struct filestat *fst, *tmp;
265*0daf62d9SStanislav Sedov 
266*0daf62d9SStanislav Sedov 	STAILQ_FOREACH_SAFE(fst, head, next, tmp) {
267*0daf62d9SStanislav Sedov 		if (fst->fs_path != NULL)
268*0daf62d9SStanislav Sedov 			free(fst->fs_path);
269*0daf62d9SStanislav Sedov 		free(fst);
270*0daf62d9SStanislav Sedov 	}
271*0daf62d9SStanislav Sedov 	free(head);
272*0daf62d9SStanislav Sedov 	if (procstat->vmentries != NULL) {
273*0daf62d9SStanislav Sedov 		free (procstat->vmentries);
274*0daf62d9SStanislav Sedov 		procstat->vmentries = NULL;
275*0daf62d9SStanislav Sedov 	}
276*0daf62d9SStanislav Sedov 	if (procstat->files != NULL) {
277*0daf62d9SStanislav Sedov 		free (procstat->files);
278*0daf62d9SStanislav Sedov 		procstat->files = NULL;
279*0daf62d9SStanislav Sedov 	}
280*0daf62d9SStanislav Sedov }
281*0daf62d9SStanislav Sedov 
282*0daf62d9SStanislav Sedov static struct filestat *
283*0daf62d9SStanislav Sedov filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags,
284*0daf62d9SStanislav Sedov     int refcount, off_t offset, char *path)
285*0daf62d9SStanislav Sedov {
286*0daf62d9SStanislav Sedov 	struct filestat *entry;
287*0daf62d9SStanislav Sedov 
288*0daf62d9SStanislav Sedov 	entry = calloc(1, sizeof(*entry));
289*0daf62d9SStanislav Sedov 	if (entry == NULL) {
290*0daf62d9SStanislav Sedov 		warn("malloc()");
291*0daf62d9SStanislav Sedov 		return (NULL);
292*0daf62d9SStanislav Sedov 	}
293*0daf62d9SStanislav Sedov 	entry->fs_typedep = typedep;
294*0daf62d9SStanislav Sedov 	entry->fs_fflags = fflags;
295*0daf62d9SStanislav Sedov 	entry->fs_uflags = uflags;
296*0daf62d9SStanislav Sedov 	entry->fs_fd = fd;
297*0daf62d9SStanislav Sedov 	entry->fs_type = type;
298*0daf62d9SStanislav Sedov 	entry->fs_ref_count = refcount;
299*0daf62d9SStanislav Sedov 	entry->fs_offset = offset;
300*0daf62d9SStanislav Sedov 	entry->fs_path = path;
301*0daf62d9SStanislav Sedov 	return (entry);
302*0daf62d9SStanislav Sedov }
303*0daf62d9SStanislav Sedov 
304*0daf62d9SStanislav Sedov static struct vnode *
305*0daf62d9SStanislav Sedov getctty(kvm_t *kd, struct kinfo_proc *kp)
306*0daf62d9SStanislav Sedov {
307*0daf62d9SStanislav Sedov 	struct pgrp pgrp;
308*0daf62d9SStanislav Sedov 	struct proc proc;
309*0daf62d9SStanislav Sedov 	struct session sess;
310*0daf62d9SStanislav Sedov 	int error;
311*0daf62d9SStanislav Sedov 
312*0daf62d9SStanislav Sedov 	assert(kp);
313*0daf62d9SStanislav Sedov 	error = kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
314*0daf62d9SStanislav Sedov 	    sizeof(proc));
315*0daf62d9SStanislav Sedov 	if (error == 0) {
316*0daf62d9SStanislav Sedov 		warnx("can't read proc struct at %p for pid %d",
317*0daf62d9SStanislav Sedov 		    kp->ki_paddr, kp->ki_pid);
318*0daf62d9SStanislav Sedov 		return (NULL);
319*0daf62d9SStanislav Sedov 	}
320*0daf62d9SStanislav Sedov 	if (proc.p_pgrp == NULL)
321*0daf62d9SStanislav Sedov 		return (NULL);
322*0daf62d9SStanislav Sedov 	error = kvm_read_all(kd, (unsigned long)proc.p_pgrp, &pgrp,
323*0daf62d9SStanislav Sedov 	    sizeof(pgrp));
324*0daf62d9SStanislav Sedov 	if (error == 0) {
325*0daf62d9SStanislav Sedov 		warnx("can't read pgrp struct at %p for pid %d",
326*0daf62d9SStanislav Sedov 		    proc.p_pgrp, kp->ki_pid);
327*0daf62d9SStanislav Sedov 		return (NULL);
328*0daf62d9SStanislav Sedov 	}
329*0daf62d9SStanislav Sedov 	error = kvm_read_all(kd, (unsigned long)pgrp.pg_session, &sess,
330*0daf62d9SStanislav Sedov 	    sizeof(sess));
331*0daf62d9SStanislav Sedov 	if (error == 0) {
332*0daf62d9SStanislav Sedov 		warnx("can't read session struct at %p for pid %d",
333*0daf62d9SStanislav Sedov 		    pgrp.pg_session, kp->ki_pid);
334*0daf62d9SStanislav Sedov 		return (NULL);
335*0daf62d9SStanislav Sedov 	}
336*0daf62d9SStanislav Sedov 	return (sess.s_ttyvp);
337*0daf62d9SStanislav Sedov }
338*0daf62d9SStanislav Sedov 
339*0daf62d9SStanislav Sedov static struct filestat_list *
340*0daf62d9SStanislav Sedov procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
341*0daf62d9SStanislav Sedov {
342*0daf62d9SStanislav Sedov 	struct file file;
343*0daf62d9SStanislav Sedov 	struct filedesc filed;
344*0daf62d9SStanislav Sedov 	struct vm_map_entry vmentry;
345*0daf62d9SStanislav Sedov 	struct vm_object object;
346*0daf62d9SStanislav Sedov 	struct vmspace vmspace;
347*0daf62d9SStanislav Sedov 	vm_map_entry_t entryp;
348*0daf62d9SStanislav Sedov 	vm_map_t map;
349*0daf62d9SStanislav Sedov 	vm_object_t objp;
350*0daf62d9SStanislav Sedov 	struct vnode *vp;
351*0daf62d9SStanislav Sedov 	struct file **ofiles;
352*0daf62d9SStanislav Sedov 	struct filestat *entry;
353*0daf62d9SStanislav Sedov 	struct filestat_list *head;
354*0daf62d9SStanislav Sedov 	kvm_t *kd;
355*0daf62d9SStanislav Sedov 	void *data;
356*0daf62d9SStanislav Sedov 	int i, fflags;
357*0daf62d9SStanislav Sedov 	int prot, type;
358*0daf62d9SStanislav Sedov 	unsigned int nfiles;
359*0daf62d9SStanislav Sedov 
360*0daf62d9SStanislav Sedov 	assert(procstat);
361*0daf62d9SStanislav Sedov 	kd = procstat->kd;
362*0daf62d9SStanislav Sedov 	if (kd == NULL)
363*0daf62d9SStanislav Sedov 		return (NULL);
364*0daf62d9SStanislav Sedov 	if (kp->ki_fd == NULL)
365*0daf62d9SStanislav Sedov 		return (NULL);
366*0daf62d9SStanislav Sedov 	if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &filed,
367*0daf62d9SStanislav Sedov 	    sizeof(filed))) {
368*0daf62d9SStanislav Sedov 		warnx("can't read filedesc at %p", (void *)kp->ki_fd);
369*0daf62d9SStanislav Sedov 		return (NULL);
370*0daf62d9SStanislav Sedov 	}
371*0daf62d9SStanislav Sedov 
372*0daf62d9SStanislav Sedov 	/*
373*0daf62d9SStanislav Sedov 	 * Allocate list head.
374*0daf62d9SStanislav Sedov 	 */
375*0daf62d9SStanislav Sedov 	head = malloc(sizeof(*head));
376*0daf62d9SStanislav Sedov 	if (head == NULL)
377*0daf62d9SStanislav Sedov 		return (NULL);
378*0daf62d9SStanislav Sedov 	STAILQ_INIT(head);
379*0daf62d9SStanislav Sedov 
380*0daf62d9SStanislav Sedov 	/* root directory vnode, if one. */
381*0daf62d9SStanislav Sedov 	if (filed.fd_rdir) {
382*0daf62d9SStanislav Sedov 		entry = filestat_new_entry(filed.fd_rdir, PS_FST_TYPE_VNODE, -1,
383*0daf62d9SStanislav Sedov 		    PS_FST_FFLAG_READ, PS_FST_UFLAG_RDIR, 0, 0, NULL);
384*0daf62d9SStanislav Sedov 		if (entry != NULL)
385*0daf62d9SStanislav Sedov 			STAILQ_INSERT_TAIL(head, entry, next);
386*0daf62d9SStanislav Sedov 	}
387*0daf62d9SStanislav Sedov 	/* current working directory vnode. */
388*0daf62d9SStanislav Sedov 	if (filed.fd_cdir) {
389*0daf62d9SStanislav Sedov 		entry = filestat_new_entry(filed.fd_cdir, PS_FST_TYPE_VNODE, -1,
390*0daf62d9SStanislav Sedov 		    PS_FST_FFLAG_READ, PS_FST_UFLAG_CDIR, 0, 0, NULL);
391*0daf62d9SStanislav Sedov 		if (entry != NULL)
392*0daf62d9SStanislav Sedov 			STAILQ_INSERT_TAIL(head, entry, next);
393*0daf62d9SStanislav Sedov 	}
394*0daf62d9SStanislav Sedov 	/* jail root, if any. */
395*0daf62d9SStanislav Sedov 	if (filed.fd_jdir) {
396*0daf62d9SStanislav Sedov 		entry = filestat_new_entry(filed.fd_jdir, PS_FST_TYPE_VNODE, -1,
397*0daf62d9SStanislav Sedov 		    PS_FST_FFLAG_READ, PS_FST_UFLAG_JAIL, 0, 0, NULL);
398*0daf62d9SStanislav Sedov 		if (entry != NULL)
399*0daf62d9SStanislav Sedov 			STAILQ_INSERT_TAIL(head, entry, next);
400*0daf62d9SStanislav Sedov 	}
401*0daf62d9SStanislav Sedov 	/* ktrace vnode, if one */
402*0daf62d9SStanislav Sedov 	if (kp->ki_tracep) {
403*0daf62d9SStanislav Sedov 		entry = filestat_new_entry(kp->ki_tracep, PS_FST_TYPE_VNODE, -1,
404*0daf62d9SStanislav Sedov 		    PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE,
405*0daf62d9SStanislav Sedov 		    PS_FST_UFLAG_TRACE, 0, 0, NULL);
406*0daf62d9SStanislav Sedov 		if (entry != NULL)
407*0daf62d9SStanislav Sedov 			STAILQ_INSERT_TAIL(head, entry, next);
408*0daf62d9SStanislav Sedov 	}
409*0daf62d9SStanislav Sedov 	/* text vnode, if one */
410*0daf62d9SStanislav Sedov 	if (kp->ki_textvp) {
411*0daf62d9SStanislav Sedov 		entry = filestat_new_entry(kp->ki_textvp, PS_FST_TYPE_VNODE, -1,
412*0daf62d9SStanislav Sedov 		    PS_FST_FFLAG_READ, PS_FST_UFLAG_TEXT, 0, 0, NULL);
413*0daf62d9SStanislav Sedov 		if (entry != NULL)
414*0daf62d9SStanislav Sedov 			STAILQ_INSERT_TAIL(head, entry, next);
415*0daf62d9SStanislav Sedov 	}
416*0daf62d9SStanislav Sedov 	/* Controlling terminal. */
417*0daf62d9SStanislav Sedov 	if ((vp = getctty(kd, kp)) != NULL) {
418*0daf62d9SStanislav Sedov 		entry = filestat_new_entry(vp, PS_FST_TYPE_VNODE, -1,
419*0daf62d9SStanislav Sedov 		    PS_FST_FFLAG_READ | PS_FST_FFLAG_WRITE,
420*0daf62d9SStanislav Sedov 		    PS_FST_UFLAG_CTTY, 0, 0, NULL);
421*0daf62d9SStanislav Sedov 		if (entry != NULL)
422*0daf62d9SStanislav Sedov 			STAILQ_INSERT_TAIL(head, entry, next);
423*0daf62d9SStanislav Sedov 	}
424*0daf62d9SStanislav Sedov 
425*0daf62d9SStanislav Sedov 	nfiles = filed.fd_lastfile + 1;
426*0daf62d9SStanislav Sedov 	ofiles = malloc(nfiles * sizeof(struct file *));
427*0daf62d9SStanislav Sedov 	if (ofiles == NULL) {
428*0daf62d9SStanislav Sedov 		warn("malloc(%zd)", nfiles * sizeof(struct file *));
429*0daf62d9SStanislav Sedov 		goto do_mmapped;
430*0daf62d9SStanislav Sedov 	}
431*0daf62d9SStanislav Sedov 	if (!kvm_read_all(kd, (unsigned long)filed.fd_ofiles, ofiles,
432*0daf62d9SStanislav Sedov 	    nfiles * sizeof(struct file *))) {
433*0daf62d9SStanislav Sedov 		warnx("cannot read file structures at %p",
434*0daf62d9SStanislav Sedov 		    (void *)filed.fd_ofiles);
435*0daf62d9SStanislav Sedov 		free(ofiles);
436*0daf62d9SStanislav Sedov 		goto do_mmapped;
437*0daf62d9SStanislav Sedov 	}
438*0daf62d9SStanislav Sedov 	for (i = 0; i <= filed.fd_lastfile; i++) {
439*0daf62d9SStanislav Sedov 		if (ofiles[i] == NULL)
440*0daf62d9SStanislav Sedov 			continue;
441*0daf62d9SStanislav Sedov 		if (!kvm_read_all(kd, (unsigned long)ofiles[i], &file,
442*0daf62d9SStanislav Sedov 		    sizeof(struct file))) {
443*0daf62d9SStanislav Sedov 			warnx("can't read file %d at %p", i,
444*0daf62d9SStanislav Sedov 			    (void *)ofiles[i]);
445*0daf62d9SStanislav Sedov 			continue;
446*0daf62d9SStanislav Sedov 		}
447*0daf62d9SStanislav Sedov 		switch (file.f_type) {
448*0daf62d9SStanislav Sedov 		case DTYPE_VNODE:
449*0daf62d9SStanislav Sedov 			type = PS_FST_TYPE_VNODE;
450*0daf62d9SStanislav Sedov 			data = file.f_vnode;
451*0daf62d9SStanislav Sedov 			break;
452*0daf62d9SStanislav Sedov 		case DTYPE_SOCKET:
453*0daf62d9SStanislav Sedov 			type = PS_FST_TYPE_SOCKET;
454*0daf62d9SStanislav Sedov 			data = file.f_data;
455*0daf62d9SStanislav Sedov 			break;
456*0daf62d9SStanislav Sedov 		case DTYPE_PIPE:
457*0daf62d9SStanislav Sedov 			type = PS_FST_TYPE_PIPE;
458*0daf62d9SStanislav Sedov 			data = file.f_data;
459*0daf62d9SStanislav Sedov 			break;
460*0daf62d9SStanislav Sedov 		case DTYPE_FIFO:
461*0daf62d9SStanislav Sedov 			type = PS_FST_TYPE_FIFO;
462*0daf62d9SStanislav Sedov 			data = file.f_vnode;
463*0daf62d9SStanislav Sedov 			break;
464*0daf62d9SStanislav Sedov #ifdef DTYPE_PTS
465*0daf62d9SStanislav Sedov 		case DTYPE_PTS:
466*0daf62d9SStanislav Sedov 			type = PS_FST_TYPE_PTS;
467*0daf62d9SStanislav Sedov 			data = file.f_data;
468*0daf62d9SStanislav Sedov 			break;
469*0daf62d9SStanislav Sedov #endif
470*0daf62d9SStanislav Sedov 		default:
471*0daf62d9SStanislav Sedov 			continue;
472*0daf62d9SStanislav Sedov 		}
473*0daf62d9SStanislav Sedov 		entry = filestat_new_entry(data, type, i,
474*0daf62d9SStanislav Sedov 		    to_filestat_flags(file.f_flag), 0, 0, 0, NULL);
475*0daf62d9SStanislav Sedov 		if (entry != NULL)
476*0daf62d9SStanislav Sedov 			STAILQ_INSERT_TAIL(head, entry, next);
477*0daf62d9SStanislav Sedov 	}
478*0daf62d9SStanislav Sedov 	free(ofiles);
479*0daf62d9SStanislav Sedov 
480*0daf62d9SStanislav Sedov do_mmapped:
481*0daf62d9SStanislav Sedov 
482*0daf62d9SStanislav Sedov 	/*
483*0daf62d9SStanislav Sedov 	 * Process mmapped files if requested.
484*0daf62d9SStanislav Sedov 	 */
485*0daf62d9SStanislav Sedov 	if (mmapped) {
486*0daf62d9SStanislav Sedov 		if (!kvm_read_all(kd, (unsigned long)kp->ki_vmspace, &vmspace,
487*0daf62d9SStanislav Sedov 		    sizeof(vmspace))) {
488*0daf62d9SStanislav Sedov 			warnx("can't read vmspace at %p",
489*0daf62d9SStanislav Sedov 			    (void *)kp->ki_vmspace);
490*0daf62d9SStanislav Sedov 			goto exit;
491*0daf62d9SStanislav Sedov 		}
492*0daf62d9SStanislav Sedov 		map = &vmspace.vm_map;
493*0daf62d9SStanislav Sedov 
494*0daf62d9SStanislav Sedov 		for (entryp = map->header.next;
495*0daf62d9SStanislav Sedov 		    entryp != &kp->ki_vmspace->vm_map.header;
496*0daf62d9SStanislav Sedov 		    entryp = vmentry.next) {
497*0daf62d9SStanislav Sedov 			if (!kvm_read_all(kd, (unsigned long)entryp, &vmentry,
498*0daf62d9SStanislav Sedov 			    sizeof(vmentry))) {
499*0daf62d9SStanislav Sedov 				warnx("can't read vm_map_entry at %p",
500*0daf62d9SStanislav Sedov 				    (void *)entryp);
501*0daf62d9SStanislav Sedov 				continue;
502*0daf62d9SStanislav Sedov 			}
503*0daf62d9SStanislav Sedov 			if (vmentry.eflags & MAP_ENTRY_IS_SUB_MAP)
504*0daf62d9SStanislav Sedov 				continue;
505*0daf62d9SStanislav Sedov 			if ((objp = vmentry.object.vm_object) == NULL)
506*0daf62d9SStanislav Sedov 				continue;
507*0daf62d9SStanislav Sedov 			for (; objp; objp = object.backing_object) {
508*0daf62d9SStanislav Sedov 				if (!kvm_read_all(kd, (unsigned long)objp,
509*0daf62d9SStanislav Sedov 				    &object, sizeof(object))) {
510*0daf62d9SStanislav Sedov 					warnx("can't read vm_object at %p",
511*0daf62d9SStanislav Sedov 					    (void *)objp);
512*0daf62d9SStanislav Sedov 					break;
513*0daf62d9SStanislav Sedov 				}
514*0daf62d9SStanislav Sedov 			}
515*0daf62d9SStanislav Sedov 
516*0daf62d9SStanislav Sedov 			/* We want only vnode objects. */
517*0daf62d9SStanislav Sedov 			if (object.type != OBJT_VNODE)
518*0daf62d9SStanislav Sedov 				continue;
519*0daf62d9SStanislav Sedov 
520*0daf62d9SStanislav Sedov 			prot = vmentry.protection;
521*0daf62d9SStanislav Sedov 			fflags = 0;
522*0daf62d9SStanislav Sedov 			if (prot & VM_PROT_READ)
523*0daf62d9SStanislav Sedov 				fflags = PS_FST_FFLAG_READ;
524*0daf62d9SStanislav Sedov 			if (prot & VM_PROT_WRITE)
525*0daf62d9SStanislav Sedov 				fflags |= PS_FST_FFLAG_WRITE;
526*0daf62d9SStanislav Sedov 
527*0daf62d9SStanislav Sedov 			/*
528*0daf62d9SStanislav Sedov 			 * Create filestat entry.
529*0daf62d9SStanislav Sedov 			 */
530*0daf62d9SStanislav Sedov 			entry = filestat_new_entry(object.handle,
531*0daf62d9SStanislav Sedov 			    PS_FST_TYPE_VNODE, -1, fflags,
532*0daf62d9SStanislav Sedov 			    PS_FST_UFLAG_MMAP, 0, 0, NULL);
533*0daf62d9SStanislav Sedov 			if (entry != NULL)
534*0daf62d9SStanislav Sedov 				STAILQ_INSERT_TAIL(head, entry, next);
535*0daf62d9SStanislav Sedov 		}
536*0daf62d9SStanislav Sedov 	}
537*0daf62d9SStanislav Sedov exit:
538*0daf62d9SStanislav Sedov 	return (head);
539*0daf62d9SStanislav Sedov }
540*0daf62d9SStanislav Sedov 
541*0daf62d9SStanislav Sedov /*
542*0daf62d9SStanislav Sedov  * kinfo types to filestat translation.
543*0daf62d9SStanislav Sedov  */
544*0daf62d9SStanislav Sedov static int
545*0daf62d9SStanislav Sedov kinfo_type2fst(int kftype)
546*0daf62d9SStanislav Sedov {
547*0daf62d9SStanislav Sedov 	static struct {
548*0daf62d9SStanislav Sedov 		int	kf_type;
549*0daf62d9SStanislav Sedov 		int	fst_type;
550*0daf62d9SStanislav Sedov 	} kftypes2fst[] = {
551*0daf62d9SStanislav Sedov 		{ KF_TYPE_CRYPTO, PS_FST_TYPE_CRYPTO },
552*0daf62d9SStanislav Sedov 		{ KF_TYPE_FIFO, PS_FST_TYPE_FIFO },
553*0daf62d9SStanislav Sedov 		{ KF_TYPE_KQUEUE, PS_FST_TYPE_KQUEUE },
554*0daf62d9SStanislav Sedov 		{ KF_TYPE_MQUEUE, PS_FST_TYPE_MQUEUE },
555*0daf62d9SStanislav Sedov 		{ KF_TYPE_NONE, PS_FST_TYPE_NONE },
556*0daf62d9SStanislav Sedov 		{ KF_TYPE_PIPE, PS_FST_TYPE_PIPE },
557*0daf62d9SStanislav Sedov 		{ KF_TYPE_PTS, PS_FST_TYPE_PTS },
558*0daf62d9SStanislav Sedov 		{ KF_TYPE_SEM, PS_FST_TYPE_SEM },
559*0daf62d9SStanislav Sedov 		{ KF_TYPE_SHM, PS_FST_TYPE_SHM },
560*0daf62d9SStanislav Sedov 		{ KF_TYPE_SOCKET, PS_FST_TYPE_SOCKET },
561*0daf62d9SStanislav Sedov 		{ KF_TYPE_VNODE, PS_FST_TYPE_VNODE },
562*0daf62d9SStanislav Sedov 		{ KF_TYPE_UNKNOWN, PS_FST_TYPE_UNKNOWN }
563*0daf62d9SStanislav Sedov 	};
564*0daf62d9SStanislav Sedov #define NKFTYPES	(sizeof(kftypes2fst) / sizeof(*kftypes2fst))
565*0daf62d9SStanislav Sedov 	unsigned int i;
566*0daf62d9SStanislav Sedov 
567*0daf62d9SStanislav Sedov 	for (i = 0; i < NKFTYPES; i++)
568*0daf62d9SStanislav Sedov 		if (kftypes2fst[i].kf_type == kftype)
569*0daf62d9SStanislav Sedov 			break;
570*0daf62d9SStanislav Sedov 	if (i == NKFTYPES)
571*0daf62d9SStanislav Sedov 		return (PS_FST_TYPE_UNKNOWN);
572*0daf62d9SStanislav Sedov 	return (kftypes2fst[i].fst_type);
573*0daf62d9SStanislav Sedov }
574*0daf62d9SStanislav Sedov 
575*0daf62d9SStanislav Sedov /*
576*0daf62d9SStanislav Sedov  * kinfo flags to filestat translation.
577*0daf62d9SStanislav Sedov  */
578*0daf62d9SStanislav Sedov static int
579*0daf62d9SStanislav Sedov kinfo_fflags2fst(int kfflags)
580*0daf62d9SStanislav Sedov {
581*0daf62d9SStanislav Sedov 	static struct {
582*0daf62d9SStanislav Sedov 		int	kf_flag;
583*0daf62d9SStanislav Sedov 		int	fst_flag;
584*0daf62d9SStanislav Sedov 	} kfflags2fst[] = {
585*0daf62d9SStanislav Sedov 		{ KF_FLAG_APPEND, PS_FST_FFLAG_APPEND },
586*0daf62d9SStanislav Sedov 		{ KF_FLAG_ASYNC, PS_FST_FFLAG_ASYNC },
587*0daf62d9SStanislav Sedov 		{ KF_FLAG_CREAT, PS_FST_FFLAG_CREAT },
588*0daf62d9SStanislav Sedov 		{ KF_FLAG_DIRECT, PS_FST_FFLAG_DIRECT },
589*0daf62d9SStanislav Sedov 		{ KF_FLAG_EXCL, PS_FST_FFLAG_EXCL },
590*0daf62d9SStanislav Sedov 		{ KF_FLAG_EXEC, PS_FST_FFLAG_EXEC },
591*0daf62d9SStanislav Sedov 		{ KF_FLAG_EXLOCK, PS_FST_FFLAG_EXLOCK },
592*0daf62d9SStanislav Sedov 		{ KF_FLAG_FSYNC, PS_FST_FFLAG_SYNC },
593*0daf62d9SStanislav Sedov 		{ KF_FLAG_HASLOCK, PS_FST_FFLAG_HASLOCK },
594*0daf62d9SStanislav Sedov 		{ KF_FLAG_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW },
595*0daf62d9SStanislav Sedov 		{ KF_FLAG_NONBLOCK, PS_FST_FFLAG_NONBLOCK },
596*0daf62d9SStanislav Sedov 		{ KF_FLAG_READ, PS_FST_FFLAG_READ },
597*0daf62d9SStanislav Sedov 		{ KF_FLAG_SHLOCK, PS_FST_FFLAG_SHLOCK },
598*0daf62d9SStanislav Sedov 		{ KF_FLAG_TRUNC, PS_FST_FFLAG_TRUNC },
599*0daf62d9SStanislav Sedov 		{ KF_FLAG_WRITE, PS_FST_FFLAG_WRITE }
600*0daf62d9SStanislav Sedov 	};
601*0daf62d9SStanislav Sedov #define NKFFLAGS	(sizeof(kfflags2fst) / sizeof(*kfflags2fst))
602*0daf62d9SStanislav Sedov 	unsigned int i;
603*0daf62d9SStanislav Sedov 	int flags;
604*0daf62d9SStanislav Sedov 
605*0daf62d9SStanislav Sedov 	flags = 0;
606*0daf62d9SStanislav Sedov 	for (i = 0; i < NKFFLAGS; i++)
607*0daf62d9SStanislav Sedov 		if ((kfflags & kfflags2fst[i].kf_flag) != 0)
608*0daf62d9SStanislav Sedov 			flags |= kfflags2fst[i].fst_flag;
609*0daf62d9SStanislav Sedov 	return (flags);
610*0daf62d9SStanislav Sedov }
611*0daf62d9SStanislav Sedov 
612*0daf62d9SStanislav Sedov static int
613*0daf62d9SStanislav Sedov kinfo_uflags2fst(int fd)
614*0daf62d9SStanislav Sedov {
615*0daf62d9SStanislav Sedov 
616*0daf62d9SStanislav Sedov 	switch (fd) {
617*0daf62d9SStanislav Sedov 	case KF_FD_TYPE_CTTY:
618*0daf62d9SStanislav Sedov 		return (PS_FST_UFLAG_CTTY);
619*0daf62d9SStanislav Sedov 	case KF_FD_TYPE_CWD:
620*0daf62d9SStanislav Sedov 		return (PS_FST_UFLAG_CDIR);
621*0daf62d9SStanislav Sedov 	case KF_FD_TYPE_JAIL:
622*0daf62d9SStanislav Sedov 		return (PS_FST_UFLAG_JAIL);
623*0daf62d9SStanislav Sedov 	case KF_FD_TYPE_TEXT:
624*0daf62d9SStanislav Sedov 		return (PS_FST_UFLAG_TEXT);
625*0daf62d9SStanislav Sedov 	case KF_FD_TYPE_TRACE:
626*0daf62d9SStanislav Sedov 		return (PS_FST_UFLAG_TRACE);
627*0daf62d9SStanislav Sedov 	case KF_FD_TYPE_ROOT:
628*0daf62d9SStanislav Sedov 		return (PS_FST_UFLAG_RDIR);
629*0daf62d9SStanislav Sedov 	}
630*0daf62d9SStanislav Sedov 	return (0);
631*0daf62d9SStanislav Sedov }
632*0daf62d9SStanislav Sedov 
633*0daf62d9SStanislav Sedov static struct filestat_list *
634*0daf62d9SStanislav Sedov procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp, int mmapped)
635*0daf62d9SStanislav Sedov {
636*0daf62d9SStanislav Sedov 	struct kinfo_file *kif, *files;
637*0daf62d9SStanislav Sedov 	struct kinfo_vmentry *kve, *vmentries;
638*0daf62d9SStanislav Sedov 	struct filestat_list *head;
639*0daf62d9SStanislav Sedov 	struct filestat *entry;
640*0daf62d9SStanislav Sedov 	char *path;
641*0daf62d9SStanislav Sedov 	off_t offset;
642*0daf62d9SStanislav Sedov 	int cnt, fd, fflags;
643*0daf62d9SStanislav Sedov 	int i, type, uflags;
644*0daf62d9SStanislav Sedov 	int refcount;
645*0daf62d9SStanislav Sedov 
646*0daf62d9SStanislav Sedov 	assert(kp);
647*0daf62d9SStanislav Sedov 	if (kp->ki_fd == NULL)
648*0daf62d9SStanislav Sedov 		return (NULL);
649*0daf62d9SStanislav Sedov 
650*0daf62d9SStanislav Sedov 	files = kinfo_getfile(kp->ki_pid, &cnt);
651*0daf62d9SStanislav Sedov 	if (files == NULL && errno != EPERM) {
652*0daf62d9SStanislav Sedov 		warn("kinfo_getfile()");
653*0daf62d9SStanislav Sedov 		return (NULL);
654*0daf62d9SStanislav Sedov 	}
655*0daf62d9SStanislav Sedov 	procstat->files = files;
656*0daf62d9SStanislav Sedov 
657*0daf62d9SStanislav Sedov 	/*
658*0daf62d9SStanislav Sedov 	 * Allocate list head.
659*0daf62d9SStanislav Sedov 	 */
660*0daf62d9SStanislav Sedov 	head = malloc(sizeof(*head));
661*0daf62d9SStanislav Sedov 	if (head == NULL)
662*0daf62d9SStanislav Sedov 		return (NULL);
663*0daf62d9SStanislav Sedov 	STAILQ_INIT(head);
664*0daf62d9SStanislav Sedov 	for (i = 0; i < cnt; i++) {
665*0daf62d9SStanislav Sedov 		kif = &files[i];
666*0daf62d9SStanislav Sedov 
667*0daf62d9SStanislav Sedov 		type = kinfo_type2fst(kif->kf_type);
668*0daf62d9SStanislav Sedov 		fd = kif->kf_fd >= 0 ? kif->kf_fd : -1;
669*0daf62d9SStanislav Sedov 		fflags = kinfo_fflags2fst(kif->kf_flags);
670*0daf62d9SStanislav Sedov 		uflags = kinfo_uflags2fst(kif->kf_fd);
671*0daf62d9SStanislav Sedov 		refcount = kif->kf_ref_count;
672*0daf62d9SStanislav Sedov 		offset = kif->kf_offset;
673*0daf62d9SStanislav Sedov 		if (*kif->kf_path != '\0')
674*0daf62d9SStanislav Sedov 			path = strdup(kif->kf_path);
675*0daf62d9SStanislav Sedov 		else
676*0daf62d9SStanislav Sedov 			path = NULL;
677*0daf62d9SStanislav Sedov 
678*0daf62d9SStanislav Sedov 		/*
679*0daf62d9SStanislav Sedov 		 * Create filestat entry.
680*0daf62d9SStanislav Sedov 		 */
681*0daf62d9SStanislav Sedov 		entry = filestat_new_entry(kif, type, fd, fflags, uflags,
682*0daf62d9SStanislav Sedov 		    refcount, offset, path);
683*0daf62d9SStanislav Sedov 		if (entry != NULL)
684*0daf62d9SStanislav Sedov 			STAILQ_INSERT_TAIL(head, entry, next);
685*0daf62d9SStanislav Sedov 	}
686*0daf62d9SStanislav Sedov 	if (mmapped != 0) {
687*0daf62d9SStanislav Sedov 		vmentries = kinfo_getvmmap(kp->ki_pid, &cnt);
688*0daf62d9SStanislav Sedov 		procstat->vmentries = vmentries;
689*0daf62d9SStanislav Sedov 		if (vmentries == NULL || cnt == 0)
690*0daf62d9SStanislav Sedov 			goto fail;
691*0daf62d9SStanislav Sedov 		for (i = 0; i < cnt; i++) {
692*0daf62d9SStanislav Sedov 			kve = &vmentries[i];
693*0daf62d9SStanislav Sedov 			if (kve->kve_type != KVME_TYPE_VNODE)
694*0daf62d9SStanislav Sedov 				continue;
695*0daf62d9SStanislav Sedov 			fflags = 0;
696*0daf62d9SStanislav Sedov 			if (kve->kve_protection & KVME_PROT_READ)
697*0daf62d9SStanislav Sedov 				fflags = PS_FST_FFLAG_READ;
698*0daf62d9SStanislav Sedov 			if (kve->kve_protection & KVME_PROT_WRITE)
699*0daf62d9SStanislav Sedov 				fflags |= PS_FST_FFLAG_WRITE;
700*0daf62d9SStanislav Sedov 			offset = kve->kve_offset;
701*0daf62d9SStanislav Sedov 			refcount = kve->kve_ref_count;
702*0daf62d9SStanislav Sedov 			if (*kve->kve_path != '\0')
703*0daf62d9SStanislav Sedov 				path = strdup(kve->kve_path);
704*0daf62d9SStanislav Sedov 			else
705*0daf62d9SStanislav Sedov 				path = NULL;
706*0daf62d9SStanislav Sedov 			entry = filestat_new_entry(kve, PS_FST_TYPE_VNODE, -1,
707*0daf62d9SStanislav Sedov 			    fflags, PS_FST_UFLAG_MMAP, refcount, offset, path);
708*0daf62d9SStanislav Sedov 			if (entry != NULL)
709*0daf62d9SStanislav Sedov 				STAILQ_INSERT_TAIL(head, entry, next);
710*0daf62d9SStanislav Sedov 		}
711*0daf62d9SStanislav Sedov 	}
712*0daf62d9SStanislav Sedov fail:
713*0daf62d9SStanislav Sedov 	return (head);
714*0daf62d9SStanislav Sedov }
715*0daf62d9SStanislav Sedov 
716*0daf62d9SStanislav Sedov int
717*0daf62d9SStanislav Sedov procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst,
718*0daf62d9SStanislav Sedov     struct pipestat *ps, char *errbuf)
719*0daf62d9SStanislav Sedov {
720*0daf62d9SStanislav Sedov 
721*0daf62d9SStanislav Sedov 	assert(ps);
722*0daf62d9SStanislav Sedov 	if (procstat->type == PROCSTAT_KVM) {
723*0daf62d9SStanislav Sedov 		return (procstat_get_pipe_info_kvm(procstat->kd, fst, ps,
724*0daf62d9SStanislav Sedov 		    errbuf));
725*0daf62d9SStanislav Sedov 	} else if (procstat->type == PROCSTAT_SYSCTL) {
726*0daf62d9SStanislav Sedov 		return (procstat_get_pipe_info_sysctl(fst, ps, errbuf));
727*0daf62d9SStanislav Sedov 	} else {
728*0daf62d9SStanislav Sedov 		warnx("unknow access method: %d", procstat->type);
729*0daf62d9SStanislav Sedov 		snprintf(errbuf, _POSIX2_LINE_MAX, "error");
730*0daf62d9SStanislav Sedov 		return (1);
731*0daf62d9SStanislav Sedov 	}
732*0daf62d9SStanislav Sedov }
733*0daf62d9SStanislav Sedov 
734*0daf62d9SStanislav Sedov static int
735*0daf62d9SStanislav Sedov procstat_get_pipe_info_kvm(kvm_t *kd, struct filestat *fst,
736*0daf62d9SStanislav Sedov     struct pipestat *ps, char *errbuf)
737*0daf62d9SStanislav Sedov {
738*0daf62d9SStanislav Sedov 	struct pipe pi;
739*0daf62d9SStanislav Sedov 	void *pipep;
740*0daf62d9SStanislav Sedov 
741*0daf62d9SStanislav Sedov 	assert(kd);
742*0daf62d9SStanislav Sedov 	assert(ps);
743*0daf62d9SStanislav Sedov 	assert(fst);
744*0daf62d9SStanislav Sedov 	bzero(ps, sizeof(*ps));
745*0daf62d9SStanislav Sedov 	pipep = fst->fs_typedep;
746*0daf62d9SStanislav Sedov 	if (pipep == NULL)
747*0daf62d9SStanislav Sedov 		goto fail;
748*0daf62d9SStanislav Sedov 	if (!kvm_read_all(kd, (unsigned long)pipep, &pi, sizeof(struct pipe))) {
749*0daf62d9SStanislav Sedov 		warnx("can't read pipe at %p", (void *)pipep);
750*0daf62d9SStanislav Sedov 		goto fail;
751*0daf62d9SStanislav Sedov 	}
752*0daf62d9SStanislav Sedov 	ps->addr = (uintptr_t)pipep;
753*0daf62d9SStanislav Sedov 	ps->peer = (uintptr_t)pi.pipe_peer;
754*0daf62d9SStanislav Sedov 	ps->buffer_cnt = pi.pipe_buffer.cnt;
755*0daf62d9SStanislav Sedov 	return (0);
756*0daf62d9SStanislav Sedov 
757*0daf62d9SStanislav Sedov fail:
758*0daf62d9SStanislav Sedov 	snprintf(errbuf, _POSIX2_LINE_MAX, "error");
759*0daf62d9SStanislav Sedov 	return (1);
760*0daf62d9SStanislav Sedov }
761*0daf62d9SStanislav Sedov 
762*0daf62d9SStanislav Sedov static int
763*0daf62d9SStanislav Sedov procstat_get_pipe_info_sysctl(struct filestat *fst, struct pipestat *ps,
764*0daf62d9SStanislav Sedov     char *errbuf __unused)
765*0daf62d9SStanislav Sedov {
766*0daf62d9SStanislav Sedov 	struct kinfo_file *kif;
767*0daf62d9SStanislav Sedov 
768*0daf62d9SStanislav Sedov 	assert(ps);
769*0daf62d9SStanislav Sedov 	assert(fst);
770*0daf62d9SStanislav Sedov 	bzero(ps, sizeof(*ps));
771*0daf62d9SStanislav Sedov 	kif = fst->fs_typedep;
772*0daf62d9SStanislav Sedov 	if (kif == NULL)
773*0daf62d9SStanislav Sedov 		return (1);
774*0daf62d9SStanislav Sedov 	ps->addr = kif->kf_un.kf_pipe.kf_pipe_addr;
775*0daf62d9SStanislav Sedov 	ps->peer = kif->kf_un.kf_pipe.kf_pipe_peer;
776*0daf62d9SStanislav Sedov 	ps->buffer_cnt = kif->kf_un.kf_pipe.kf_pipe_buffer_cnt;
777*0daf62d9SStanislav Sedov 	return (0);
778*0daf62d9SStanislav Sedov }
779*0daf62d9SStanislav Sedov 
780*0daf62d9SStanislav Sedov int
781*0daf62d9SStanislav Sedov procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,
782*0daf62d9SStanislav Sedov     struct ptsstat *pts, char *errbuf)
783*0daf62d9SStanislav Sedov {
784*0daf62d9SStanislav Sedov 
785*0daf62d9SStanislav Sedov 	assert(pts);
786*0daf62d9SStanislav Sedov 	if (procstat->type == PROCSTAT_KVM) {
787*0daf62d9SStanislav Sedov 		return (procstat_get_pts_info_kvm(procstat->kd, fst, pts,
788*0daf62d9SStanislav Sedov 		    errbuf));
789*0daf62d9SStanislav Sedov 	} else if (procstat->type == PROCSTAT_SYSCTL) {
790*0daf62d9SStanislav Sedov 		return (procstat_get_pts_info_sysctl(fst, pts, errbuf));
791*0daf62d9SStanislav Sedov 	} else {
792*0daf62d9SStanislav Sedov 		warnx("unknow access method: %d", procstat->type);
793*0daf62d9SStanislav Sedov 		snprintf(errbuf, _POSIX2_LINE_MAX, "error");
794*0daf62d9SStanislav Sedov 		return (1);
795*0daf62d9SStanislav Sedov 	}
796*0daf62d9SStanislav Sedov }
797*0daf62d9SStanislav Sedov 
798*0daf62d9SStanislav Sedov static int
799*0daf62d9SStanislav Sedov procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst,
800*0daf62d9SStanislav Sedov     struct ptsstat *pts, char *errbuf)
801*0daf62d9SStanislav Sedov {
802*0daf62d9SStanislav Sedov 	struct tty tty;
803*0daf62d9SStanislav Sedov 	void *ttyp;
804*0daf62d9SStanislav Sedov 
805*0daf62d9SStanislav Sedov 	assert(kd);
806*0daf62d9SStanislav Sedov 	assert(pts);
807*0daf62d9SStanislav Sedov 	assert(fst);
808*0daf62d9SStanislav Sedov 	bzero(pts, sizeof(*pts));
809*0daf62d9SStanislav Sedov 	ttyp = fst->fs_typedep;
810*0daf62d9SStanislav Sedov 	if (ttyp == NULL)
811*0daf62d9SStanislav Sedov 		goto fail;
812*0daf62d9SStanislav Sedov 	if (!kvm_read_all(kd, (unsigned long)ttyp, &tty, sizeof(struct tty))) {
813*0daf62d9SStanislav Sedov 		warnx("can't read tty at %p", (void *)ttyp);
814*0daf62d9SStanislav Sedov 		goto fail;
815*0daf62d9SStanislav Sedov 	}
816*0daf62d9SStanislav Sedov 	pts->dev = dev2udev(kd, tty.t_dev);
817*0daf62d9SStanislav Sedov 	(void)kdevtoname(kd, tty.t_dev, pts->devname);
818*0daf62d9SStanislav Sedov 	return (0);
819*0daf62d9SStanislav Sedov 
820*0daf62d9SStanislav Sedov fail:
821*0daf62d9SStanislav Sedov 	snprintf(errbuf, _POSIX2_LINE_MAX, "error");
822*0daf62d9SStanislav Sedov 	return (1);
823*0daf62d9SStanislav Sedov }
824*0daf62d9SStanislav Sedov 
825*0daf62d9SStanislav Sedov static int
826*0daf62d9SStanislav Sedov procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts,
827*0daf62d9SStanislav Sedov     char *errbuf __unused)
828*0daf62d9SStanislav Sedov {
829*0daf62d9SStanislav Sedov 	struct kinfo_file *kif;
830*0daf62d9SStanislav Sedov 
831*0daf62d9SStanislav Sedov 	assert(pts);
832*0daf62d9SStanislav Sedov 	assert(fst);
833*0daf62d9SStanislav Sedov 	bzero(pts, sizeof(*pts));
834*0daf62d9SStanislav Sedov 	kif = fst->fs_typedep;
835*0daf62d9SStanislav Sedov 	if (kif == NULL)
836*0daf62d9SStanislav Sedov 		return (0);
837*0daf62d9SStanislav Sedov 	pts->dev = kif->kf_un.kf_pts.kf_pts_dev;
838*0daf62d9SStanislav Sedov 	strlcpy(pts->devname, kif->kf_path, sizeof(pts->devname));
839*0daf62d9SStanislav Sedov 	return (0);
840*0daf62d9SStanislav Sedov }
841*0daf62d9SStanislav Sedov 
842*0daf62d9SStanislav Sedov int
843*0daf62d9SStanislav Sedov procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
844*0daf62d9SStanislav Sedov     struct vnstat *vn, char *errbuf)
845*0daf62d9SStanislav Sedov {
846*0daf62d9SStanislav Sedov 
847*0daf62d9SStanislav Sedov 	assert(vn);
848*0daf62d9SStanislav Sedov 	if (procstat->type == PROCSTAT_KVM) {
849*0daf62d9SStanislav Sedov 		return (procstat_get_vnode_info_kvm(procstat->kd, fst, vn,
850*0daf62d9SStanislav Sedov 		    errbuf));
851*0daf62d9SStanislav Sedov 	} else if (procstat->type == PROCSTAT_SYSCTL) {
852*0daf62d9SStanislav Sedov 		return (procstat_get_vnode_info_sysctl(fst, vn, errbuf));
853*0daf62d9SStanislav Sedov 	} else {
854*0daf62d9SStanislav Sedov 		warnx("unknow access method: %d", procstat->type);
855*0daf62d9SStanislav Sedov 		snprintf(errbuf, _POSIX2_LINE_MAX, "error");
856*0daf62d9SStanislav Sedov 		return (1);
857*0daf62d9SStanislav Sedov 	}
858*0daf62d9SStanislav Sedov }
859*0daf62d9SStanislav Sedov 
860*0daf62d9SStanislav Sedov static int
861*0daf62d9SStanislav Sedov procstat_get_vnode_info_kvm(kvm_t *kd, struct filestat *fst,
862*0daf62d9SStanislav Sedov     struct vnstat *vn, char *errbuf)
863*0daf62d9SStanislav Sedov {
864*0daf62d9SStanislav Sedov 	/* Filesystem specific handlers. */
865*0daf62d9SStanislav Sedov 	#define FSTYPE(fst)     {#fst, fst##_filestat}
866*0daf62d9SStanislav Sedov 	struct {
867*0daf62d9SStanislav Sedov 		const char	*tag;
868*0daf62d9SStanislav Sedov 		int		(*handler)(kvm_t *kd, struct vnode *vp,
869*0daf62d9SStanislav Sedov 		    struct vnstat *vn);
870*0daf62d9SStanislav Sedov 	} fstypes[] = {
871*0daf62d9SStanislav Sedov 		FSTYPE(devfs),
872*0daf62d9SStanislav Sedov 		FSTYPE(isofs),
873*0daf62d9SStanislav Sedov 		FSTYPE(msdosfs),
874*0daf62d9SStanislav Sedov 		FSTYPE(nfs),
875*0daf62d9SStanislav Sedov 		FSTYPE(ntfs),
876*0daf62d9SStanislav Sedov 		FSTYPE(nwfs),
877*0daf62d9SStanislav Sedov 		FSTYPE(smbfs),
878*0daf62d9SStanislav Sedov 		FSTYPE(udf),
879*0daf62d9SStanislav Sedov 		FSTYPE(ufs),
880*0daf62d9SStanislav Sedov #ifdef ZFS
881*0daf62d9SStanislav Sedov 		FSTYPE(zfs),
882*0daf62d9SStanislav Sedov #endif
883*0daf62d9SStanislav Sedov 	};
884*0daf62d9SStanislav Sedov #define	NTYPES	(sizeof(fstypes) / sizeof(*fstypes))
885*0daf62d9SStanislav Sedov 	struct vnode vnode;
886*0daf62d9SStanislav Sedov 	char tagstr[12];
887*0daf62d9SStanislav Sedov 	void *vp;
888*0daf62d9SStanislav Sedov 	int error, found;
889*0daf62d9SStanislav Sedov 	unsigned int i;
890*0daf62d9SStanislav Sedov 
891*0daf62d9SStanislav Sedov 	assert(kd);
892*0daf62d9SStanislav Sedov 	assert(vn);
893*0daf62d9SStanislav Sedov 	assert(fst);
894*0daf62d9SStanislav Sedov 	vp = fst->fs_typedep;
895*0daf62d9SStanislav Sedov 	if (vp == NULL)
896*0daf62d9SStanislav Sedov 		goto fail;
897*0daf62d9SStanislav Sedov 	error = kvm_read_all(kd, (unsigned long)vp, &vnode, sizeof(vnode));
898*0daf62d9SStanislav Sedov 	if (error == 0) {
899*0daf62d9SStanislav Sedov 		warnx("can't read vnode at %p", (void *)vp);
900*0daf62d9SStanislav Sedov 		goto fail;
901*0daf62d9SStanislav Sedov 	}
902*0daf62d9SStanislav Sedov 	bzero(vn, sizeof(*vn));
903*0daf62d9SStanislav Sedov 	vn->vn_type = vntype2psfsttype(vnode.v_type);
904*0daf62d9SStanislav Sedov 	if (vnode.v_type == VNON || vnode.v_type == VBAD)
905*0daf62d9SStanislav Sedov 		return (0);
906*0daf62d9SStanislav Sedov 	error = kvm_read_all(kd, (unsigned long)vnode.v_tag, tagstr,
907*0daf62d9SStanislav Sedov 	    sizeof(tagstr));
908*0daf62d9SStanislav Sedov 	if (error == 0) {
909*0daf62d9SStanislav Sedov 		warnx("can't read v_tag at %p", (void *)vp);
910*0daf62d9SStanislav Sedov 		goto fail;
911*0daf62d9SStanislav Sedov 	}
912*0daf62d9SStanislav Sedov 	tagstr[sizeof(tagstr) - 1] = '\0';
913*0daf62d9SStanislav Sedov 
914*0daf62d9SStanislav Sedov 	/*
915*0daf62d9SStanislav Sedov 	 * Find appropriate handler.
916*0daf62d9SStanislav Sedov 	 */
917*0daf62d9SStanislav Sedov 	for (i = 0, found = 0; i < NTYPES; i++)
918*0daf62d9SStanislav Sedov 		if (!strcmp(fstypes[i].tag, tagstr)) {
919*0daf62d9SStanislav Sedov 			if (fstypes[i].handler(kd, &vnode, vn) != 0) {
920*0daf62d9SStanislav Sedov 				goto fail;
921*0daf62d9SStanislav Sedov 			}
922*0daf62d9SStanislav Sedov 			break;
923*0daf62d9SStanislav Sedov 		}
924*0daf62d9SStanislav Sedov 	if (i == NTYPES) {
925*0daf62d9SStanislav Sedov 		snprintf(errbuf, _POSIX2_LINE_MAX, "?(%s)", tagstr);
926*0daf62d9SStanislav Sedov 		return (1);
927*0daf62d9SStanislav Sedov 	}
928*0daf62d9SStanislav Sedov 	vn->vn_mntdir = getmnton(kd, vnode.v_mount);
929*0daf62d9SStanislav Sedov 	if ((vnode.v_type == VBLK || vnode.v_type == VCHR) &&
930*0daf62d9SStanislav Sedov 	    vnode.v_rdev != NULL){
931*0daf62d9SStanislav Sedov 		vn->vn_dev = dev2udev(kd, vnode.v_rdev);
932*0daf62d9SStanislav Sedov 		(void)kdevtoname(kd, vnode.v_rdev, vn->vn_devname);
933*0daf62d9SStanislav Sedov 	} else {
934*0daf62d9SStanislav Sedov 		vn->vn_dev = -1;
935*0daf62d9SStanislav Sedov 	}
936*0daf62d9SStanislav Sedov 	return (0);
937*0daf62d9SStanislav Sedov 
938*0daf62d9SStanislav Sedov fail:
939*0daf62d9SStanislav Sedov 	snprintf(errbuf, _POSIX2_LINE_MAX, "error");
940*0daf62d9SStanislav Sedov 	return (1);
941*0daf62d9SStanislav Sedov }
942*0daf62d9SStanislav Sedov 
943*0daf62d9SStanislav Sedov /*
944*0daf62d9SStanislav Sedov  * kinfo vnode type to filestat translation.
945*0daf62d9SStanislav Sedov  */
946*0daf62d9SStanislav Sedov static int
947*0daf62d9SStanislav Sedov kinfo_vtype2fst(int kfvtype)
948*0daf62d9SStanislav Sedov {
949*0daf62d9SStanislav Sedov 	static struct {
950*0daf62d9SStanislav Sedov 		int	kf_vtype;
951*0daf62d9SStanislav Sedov 		int	fst_vtype;
952*0daf62d9SStanislav Sedov 	} kfvtypes2fst[] = {
953*0daf62d9SStanislav Sedov 		{ KF_VTYPE_VBAD, PS_FST_VTYPE_VBAD },
954*0daf62d9SStanislav Sedov 		{ KF_VTYPE_VBLK, PS_FST_VTYPE_VBLK },
955*0daf62d9SStanislav Sedov 		{ KF_VTYPE_VCHR, PS_FST_VTYPE_VCHR },
956*0daf62d9SStanislav Sedov 		{ KF_VTYPE_VDIR, PS_FST_VTYPE_VDIR },
957*0daf62d9SStanislav Sedov 		{ KF_VTYPE_VFIFO, PS_FST_VTYPE_VFIFO },
958*0daf62d9SStanislav Sedov 		{ KF_VTYPE_VLNK, PS_FST_VTYPE_VLNK },
959*0daf62d9SStanislav Sedov 		{ KF_VTYPE_VNON, PS_FST_VTYPE_VNON },
960*0daf62d9SStanislav Sedov 		{ KF_VTYPE_VREG, PS_FST_VTYPE_VREG },
961*0daf62d9SStanislav Sedov 		{ KF_VTYPE_VSOCK, PS_FST_VTYPE_VSOCK }
962*0daf62d9SStanislav Sedov 	};
963*0daf62d9SStanislav Sedov #define	NKFVTYPES	(sizeof(kfvtypes2fst) / sizeof(*kfvtypes2fst))
964*0daf62d9SStanislav Sedov 	unsigned int i;
965*0daf62d9SStanislav Sedov 
966*0daf62d9SStanislav Sedov 	for (i = 0; i < NKFVTYPES; i++)
967*0daf62d9SStanislav Sedov 		if (kfvtypes2fst[i].kf_vtype == kfvtype)
968*0daf62d9SStanislav Sedov 			break;
969*0daf62d9SStanislav Sedov 	if (i == NKFVTYPES)
970*0daf62d9SStanislav Sedov 		return (PS_FST_VTYPE_UNKNOWN);
971*0daf62d9SStanislav Sedov 	return (kfvtypes2fst[i].fst_vtype);
972*0daf62d9SStanislav Sedov }
973*0daf62d9SStanislav Sedov 
974*0daf62d9SStanislav Sedov static int
975*0daf62d9SStanislav Sedov procstat_get_vnode_info_sysctl(struct filestat *fst, struct vnstat *vn,
976*0daf62d9SStanislav Sedov     char *errbuf)
977*0daf62d9SStanislav Sedov {
978*0daf62d9SStanislav Sedov 	struct statfs stbuf;
979*0daf62d9SStanislav Sedov 	struct kinfo_file *kif;
980*0daf62d9SStanislav Sedov 	struct kinfo_vmentry *kve;
981*0daf62d9SStanislav Sedov 	uint64_t fileid;
982*0daf62d9SStanislav Sedov 	uint64_t size;
983*0daf62d9SStanislav Sedov 	char *name, *path;
984*0daf62d9SStanislav Sedov 	uint32_t fsid;
985*0daf62d9SStanislav Sedov 	uint16_t mode;
986*0daf62d9SStanislav Sedov 	uint32_t rdev;
987*0daf62d9SStanislav Sedov 	int vntype;
988*0daf62d9SStanislav Sedov 	int status;
989*0daf62d9SStanislav Sedov 
990*0daf62d9SStanislav Sedov 	assert(fst);
991*0daf62d9SStanislav Sedov 	assert(vn);
992*0daf62d9SStanislav Sedov 	bzero(vn, sizeof(*vn));
993*0daf62d9SStanislav Sedov 	if (fst->fs_typedep == NULL)
994*0daf62d9SStanislav Sedov 		return (1);
995*0daf62d9SStanislav Sedov 	if (fst->fs_uflags & PS_FST_UFLAG_MMAP) {
996*0daf62d9SStanislav Sedov 		kve = fst->fs_typedep;
997*0daf62d9SStanislav Sedov 		fileid = kve->kve_vn_fileid;
998*0daf62d9SStanislav Sedov 		fsid = kve->kve_vn_fsid;
999*0daf62d9SStanislav Sedov 		mode = kve->kve_vn_mode;
1000*0daf62d9SStanislav Sedov 		path = kve->kve_path;
1001*0daf62d9SStanislav Sedov 		rdev = kve->kve_vn_rdev;
1002*0daf62d9SStanislav Sedov 		size = kve->kve_vn_size;
1003*0daf62d9SStanislav Sedov 		vntype = kinfo_vtype2fst(kve->kve_vn_type);
1004*0daf62d9SStanislav Sedov 		status = kve->kve_status;
1005*0daf62d9SStanislav Sedov 	} else {
1006*0daf62d9SStanislav Sedov 		kif = fst->fs_typedep;
1007*0daf62d9SStanislav Sedov 		fileid = kif->kf_un.kf_file.kf_file_fileid;
1008*0daf62d9SStanislav Sedov 		fsid = kif->kf_un.kf_file.kf_file_fsid;
1009*0daf62d9SStanislav Sedov 		mode = kif->kf_un.kf_file.kf_file_mode;
1010*0daf62d9SStanislav Sedov 		path = kif->kf_path;
1011*0daf62d9SStanislav Sedov 		rdev = kif->kf_un.kf_file.kf_file_rdev;
1012*0daf62d9SStanislav Sedov 		size = kif->kf_un.kf_file.kf_file_size;
1013*0daf62d9SStanislav Sedov 		vntype = kinfo_vtype2fst(kif->kf_vnode_type);
1014*0daf62d9SStanislav Sedov 		status = kif->kf_status;
1015*0daf62d9SStanislav Sedov 	}
1016*0daf62d9SStanislav Sedov 	vn->vn_type = vntype;
1017*0daf62d9SStanislav Sedov 	if (vntype == PS_FST_VTYPE_VNON || vntype == PS_FST_VTYPE_VBAD)
1018*0daf62d9SStanislav Sedov 		return (0);
1019*0daf62d9SStanislav Sedov 	if ((status & KF_ATTR_VALID) == 0) {
1020*0daf62d9SStanislav Sedov 		snprintf(errbuf, _POSIX2_LINE_MAX, "? (no info available)");
1021*0daf62d9SStanislav Sedov 		return (1);
1022*0daf62d9SStanislav Sedov 	}
1023*0daf62d9SStanislav Sedov 	if (path && *path) {
1024*0daf62d9SStanislav Sedov 		statfs(path, &stbuf);
1025*0daf62d9SStanislav Sedov 		vn->vn_mntdir = strdup(stbuf.f_mntonname);
1026*0daf62d9SStanislav Sedov 	} else
1027*0daf62d9SStanislav Sedov 		vn->vn_mntdir = strdup("-");
1028*0daf62d9SStanislav Sedov 	vn->vn_dev = rdev;
1029*0daf62d9SStanislav Sedov 	if (vntype == PS_FST_VTYPE_VBLK) {
1030*0daf62d9SStanislav Sedov 		name = devname(rdev, S_IFBLK);
1031*0daf62d9SStanislav Sedov 		if (name != NULL)
1032*0daf62d9SStanislav Sedov 			strlcpy(vn->vn_devname, name,
1033*0daf62d9SStanislav Sedov 			    sizeof(vn->vn_devname));
1034*0daf62d9SStanislav Sedov 	} else if (vntype == PS_FST_VTYPE_VCHR) {
1035*0daf62d9SStanislav Sedov 		name = devname(vn->vn_dev, S_IFCHR);
1036*0daf62d9SStanislav Sedov 		if (name != NULL)
1037*0daf62d9SStanislav Sedov 			strlcpy(vn->vn_devname, name,
1038*0daf62d9SStanislav Sedov 			    sizeof(vn->vn_devname));
1039*0daf62d9SStanislav Sedov 	}
1040*0daf62d9SStanislav Sedov 	vn->vn_fsid = fsid;
1041*0daf62d9SStanislav Sedov 	vn->vn_fileid = fileid;
1042*0daf62d9SStanislav Sedov 	vn->vn_size = size;
1043*0daf62d9SStanislav Sedov 	vn->vn_mode = mode;
1044*0daf62d9SStanislav Sedov 	return (0);
1045*0daf62d9SStanislav Sedov }
1046*0daf62d9SStanislav Sedov 
1047*0daf62d9SStanislav Sedov int
1048*0daf62d9SStanislav Sedov procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
1049*0daf62d9SStanislav Sedov     struct sockstat *sock, char *errbuf)
1050*0daf62d9SStanislav Sedov {
1051*0daf62d9SStanislav Sedov 
1052*0daf62d9SStanislav Sedov 	assert(sock);
1053*0daf62d9SStanislav Sedov 	if (procstat->type == PROCSTAT_KVM) {
1054*0daf62d9SStanislav Sedov 		return (procstat_get_socket_info_kvm(procstat->kd, fst, sock,
1055*0daf62d9SStanislav Sedov 		    errbuf));
1056*0daf62d9SStanislav Sedov 	} else if (procstat->type == PROCSTAT_SYSCTL) {
1057*0daf62d9SStanislav Sedov 		return (procstat_get_socket_info_sysctl(fst, sock, errbuf));
1058*0daf62d9SStanislav Sedov 	} else {
1059*0daf62d9SStanislav Sedov 		warnx("unknow access method: %d", procstat->type);
1060*0daf62d9SStanislav Sedov 		snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1061*0daf62d9SStanislav Sedov 		return (1);
1062*0daf62d9SStanislav Sedov 	}
1063*0daf62d9SStanislav Sedov }
1064*0daf62d9SStanislav Sedov 
1065*0daf62d9SStanislav Sedov static int
1066*0daf62d9SStanislav Sedov procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst,
1067*0daf62d9SStanislav Sedov     struct sockstat *sock, char *errbuf)
1068*0daf62d9SStanislav Sedov {
1069*0daf62d9SStanislav Sedov 	struct domain dom;
1070*0daf62d9SStanislav Sedov 	struct inpcb inpcb;
1071*0daf62d9SStanislav Sedov 	struct protosw proto;
1072*0daf62d9SStanislav Sedov 	struct socket s;
1073*0daf62d9SStanislav Sedov 	struct unpcb unpcb;
1074*0daf62d9SStanislav Sedov 	ssize_t len;
1075*0daf62d9SStanislav Sedov 	void *so;
1076*0daf62d9SStanislav Sedov 
1077*0daf62d9SStanislav Sedov 	assert(kd);
1078*0daf62d9SStanislav Sedov 	assert(sock);
1079*0daf62d9SStanislav Sedov 	assert(fst);
1080*0daf62d9SStanislav Sedov 	bzero(sock, sizeof(*sock));
1081*0daf62d9SStanislav Sedov 	so = fst->fs_typedep;
1082*0daf62d9SStanislav Sedov 	if (so == NULL)
1083*0daf62d9SStanislav Sedov 		goto fail;
1084*0daf62d9SStanislav Sedov 	sock->so_addr = (uintptr_t)so;
1085*0daf62d9SStanislav Sedov 	/* fill in socket */
1086*0daf62d9SStanislav Sedov 	if (!kvm_read_all(kd, (unsigned long)so, &s,
1087*0daf62d9SStanislav Sedov 	    sizeof(struct socket))) {
1088*0daf62d9SStanislav Sedov 		warnx("can't read sock at %p", (void *)so);
1089*0daf62d9SStanislav Sedov 		goto fail;
1090*0daf62d9SStanislav Sedov 	}
1091*0daf62d9SStanislav Sedov 	/* fill in protosw entry */
1092*0daf62d9SStanislav Sedov 	if (!kvm_read_all(kd, (unsigned long)s.so_proto, &proto,
1093*0daf62d9SStanislav Sedov 	    sizeof(struct protosw))) {
1094*0daf62d9SStanislav Sedov 		warnx("can't read protosw at %p", (void *)s.so_proto);
1095*0daf62d9SStanislav Sedov 		goto fail;
1096*0daf62d9SStanislav Sedov 	}
1097*0daf62d9SStanislav Sedov 	/* fill in domain */
1098*0daf62d9SStanislav Sedov 	if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom,
1099*0daf62d9SStanislav Sedov 	    sizeof(struct domain))) {
1100*0daf62d9SStanislav Sedov 		warnx("can't read domain at %p",
1101*0daf62d9SStanislav Sedov 		    (void *)proto.pr_domain);
1102*0daf62d9SStanislav Sedov 		goto fail;
1103*0daf62d9SStanislav Sedov 	}
1104*0daf62d9SStanislav Sedov 	if ((len = kvm_read(kd, (unsigned long)dom.dom_name, sock->dname,
1105*0daf62d9SStanislav Sedov 	    sizeof(sock->dname) - 1)) < 0) {
1106*0daf62d9SStanislav Sedov 		warnx("can't read domain name at %p", (void *)dom.dom_name);
1107*0daf62d9SStanislav Sedov 		sock->dname[0] = '\0';
1108*0daf62d9SStanislav Sedov 	}
1109*0daf62d9SStanislav Sedov 	else
1110*0daf62d9SStanislav Sedov 		sock->dname[len] = '\0';
1111*0daf62d9SStanislav Sedov 
1112*0daf62d9SStanislav Sedov 	/*
1113*0daf62d9SStanislav Sedov 	 * Fill in known data.
1114*0daf62d9SStanislav Sedov 	 */
1115*0daf62d9SStanislav Sedov 	sock->type = s.so_type;
1116*0daf62d9SStanislav Sedov 	sock->proto = proto.pr_protocol;
1117*0daf62d9SStanislav Sedov 	sock->dom_family = dom.dom_family;
1118*0daf62d9SStanislav Sedov 	sock->so_pcb = (uintptr_t)s.so_pcb;
1119*0daf62d9SStanislav Sedov 
1120*0daf62d9SStanislav Sedov 	/*
1121*0daf62d9SStanislav Sedov 	 * Protocol specific data.
1122*0daf62d9SStanislav Sedov 	 */
1123*0daf62d9SStanislav Sedov 	switch(dom.dom_family) {
1124*0daf62d9SStanislav Sedov 	case AF_INET:
1125*0daf62d9SStanislav Sedov 	case AF_INET6:
1126*0daf62d9SStanislav Sedov 		if (proto.pr_protocol == IPPROTO_TCP) {
1127*0daf62d9SStanislav Sedov 			if (s.so_pcb) {
1128*0daf62d9SStanislav Sedov 				if (kvm_read(kd, (u_long)s.so_pcb,
1129*0daf62d9SStanislav Sedov 				    (char *)&inpcb, sizeof(struct inpcb))
1130*0daf62d9SStanislav Sedov 				    != sizeof(struct inpcb)) {
1131*0daf62d9SStanislav Sedov 					warnx("can't read inpcb at %p",
1132*0daf62d9SStanislav Sedov 					    (void *)s.so_pcb);
1133*0daf62d9SStanislav Sedov 				} else
1134*0daf62d9SStanislav Sedov 					sock->inp_ppcb =
1135*0daf62d9SStanislav Sedov 					    (uintptr_t)inpcb.inp_ppcb;
1136*0daf62d9SStanislav Sedov 			}
1137*0daf62d9SStanislav Sedov 		}
1138*0daf62d9SStanislav Sedov 		break;
1139*0daf62d9SStanislav Sedov 	case AF_UNIX:
1140*0daf62d9SStanislav Sedov 		if (s.so_pcb) {
1141*0daf62d9SStanislav Sedov 			if (kvm_read(kd, (u_long)s.so_pcb, (char *)&unpcb,
1142*0daf62d9SStanislav Sedov 			    sizeof(struct unpcb)) != sizeof(struct unpcb)){
1143*0daf62d9SStanislav Sedov 				warnx("can't read unpcb at %p",
1144*0daf62d9SStanislav Sedov 				    (void *)s.so_pcb);
1145*0daf62d9SStanislav Sedov 			} else if (unpcb.unp_conn) {
1146*0daf62d9SStanislav Sedov 				sock->so_rcv_sb_state = s.so_rcv.sb_state;
1147*0daf62d9SStanislav Sedov 				sock->so_snd_sb_state = s.so_snd.sb_state;
1148*0daf62d9SStanislav Sedov 				sock->unp_conn = (uintptr_t)unpcb.unp_conn;
1149*0daf62d9SStanislav Sedov 			}
1150*0daf62d9SStanislav Sedov 		}
1151*0daf62d9SStanislav Sedov 		break;
1152*0daf62d9SStanislav Sedov 	default:
1153*0daf62d9SStanislav Sedov 		break;
1154*0daf62d9SStanislav Sedov 	}
1155*0daf62d9SStanislav Sedov 	return (0);
1156*0daf62d9SStanislav Sedov 
1157*0daf62d9SStanislav Sedov fail:
1158*0daf62d9SStanislav Sedov 	snprintf(errbuf, _POSIX2_LINE_MAX, "error");
1159*0daf62d9SStanislav Sedov 	return (1);
1160*0daf62d9SStanislav Sedov }
1161*0daf62d9SStanislav Sedov 
1162*0daf62d9SStanislav Sedov static int
1163*0daf62d9SStanislav Sedov procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock,
1164*0daf62d9SStanislav Sedov     char *errbuf __unused)
1165*0daf62d9SStanislav Sedov {
1166*0daf62d9SStanislav Sedov 	struct kinfo_file *kif;
1167*0daf62d9SStanislav Sedov 
1168*0daf62d9SStanislav Sedov 	assert(sock);
1169*0daf62d9SStanislav Sedov 	assert(fst);
1170*0daf62d9SStanislav Sedov 	bzero(sock, sizeof(*sock));
1171*0daf62d9SStanislav Sedov 	kif = fst->fs_typedep;
1172*0daf62d9SStanislav Sedov 	if (kif == NULL)
1173*0daf62d9SStanislav Sedov 		return (0);
1174*0daf62d9SStanislav Sedov 
1175*0daf62d9SStanislav Sedov 	/*
1176*0daf62d9SStanislav Sedov 	 * Fill in known data.
1177*0daf62d9SStanislav Sedov 	 */
1178*0daf62d9SStanislav Sedov 	sock->type = kif->kf_sock_type;
1179*0daf62d9SStanislav Sedov 	sock->proto = kif->kf_sock_protocol;
1180*0daf62d9SStanislav Sedov 	sock->dom_family = kif->kf_sock_domain;
1181*0daf62d9SStanislav Sedov 	sock->so_pcb = kif->kf_un.kf_sock.kf_sock_pcb;
1182*0daf62d9SStanislav Sedov 	strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname));
1183*0daf62d9SStanislav Sedov 	bcopy(&kif->kf_sa_local, &sock->sa_local, kif->kf_sa_local.ss_len);
1184*0daf62d9SStanislav Sedov 	bcopy(&kif->kf_sa_peer, &sock->sa_peer, kif->kf_sa_peer.ss_len);
1185*0daf62d9SStanislav Sedov 
1186*0daf62d9SStanislav Sedov 	/*
1187*0daf62d9SStanislav Sedov 	 * Protocol specific data.
1188*0daf62d9SStanislav Sedov 	 */
1189*0daf62d9SStanislav Sedov 	switch(sock->dom_family) {
1190*0daf62d9SStanislav Sedov 	case AF_INET:
1191*0daf62d9SStanislav Sedov 	case AF_INET6:
1192*0daf62d9SStanislav Sedov 		if (sock->proto == IPPROTO_TCP)
1193*0daf62d9SStanislav Sedov 			sock->inp_ppcb = kif->kf_un.kf_sock.kf_sock_inpcb;
1194*0daf62d9SStanislav Sedov 		break;
1195*0daf62d9SStanislav Sedov 	case AF_UNIX:
1196*0daf62d9SStanislav Sedov 		if (kif->kf_un.kf_sock.kf_sock_unpconn != 0) {
1197*0daf62d9SStanislav Sedov 				sock->so_rcv_sb_state =
1198*0daf62d9SStanislav Sedov 				    kif->kf_un.kf_sock.kf_sock_rcv_sb_state;
1199*0daf62d9SStanislav Sedov 				sock->so_snd_sb_state =
1200*0daf62d9SStanislav Sedov 				    kif->kf_un.kf_sock.kf_sock_snd_sb_state;
1201*0daf62d9SStanislav Sedov 				sock->unp_conn =
1202*0daf62d9SStanislav Sedov 				    kif->kf_un.kf_sock.kf_sock_unpconn;
1203*0daf62d9SStanislav Sedov 		}
1204*0daf62d9SStanislav Sedov 		break;
1205*0daf62d9SStanislav Sedov 	default:
1206*0daf62d9SStanislav Sedov 		break;
1207*0daf62d9SStanislav Sedov 	}
1208*0daf62d9SStanislav Sedov 	return (0);
1209*0daf62d9SStanislav Sedov }
1210*0daf62d9SStanislav Sedov 
1211*0daf62d9SStanislav Sedov /*
1212*0daf62d9SStanislav Sedov  * Descriptor flags to filestat translation.
1213*0daf62d9SStanislav Sedov  */
1214*0daf62d9SStanislav Sedov static int
1215*0daf62d9SStanislav Sedov to_filestat_flags(int flags)
1216*0daf62d9SStanislav Sedov {
1217*0daf62d9SStanislav Sedov 	static struct {
1218*0daf62d9SStanislav Sedov 		int flag;
1219*0daf62d9SStanislav Sedov 		int fst_flag;
1220*0daf62d9SStanislav Sedov 	} fstflags[] = {
1221*0daf62d9SStanislav Sedov 		{ FREAD, PS_FST_FFLAG_READ },
1222*0daf62d9SStanislav Sedov 		{ FWRITE, PS_FST_FFLAG_WRITE },
1223*0daf62d9SStanislav Sedov 		{ O_APPEND, PS_FST_FFLAG_APPEND },
1224*0daf62d9SStanislav Sedov 		{ O_ASYNC, PS_FST_FFLAG_ASYNC },
1225*0daf62d9SStanislav Sedov 		{ O_CREAT, PS_FST_FFLAG_CREAT },
1226*0daf62d9SStanislav Sedov 		{ O_DIRECT, PS_FST_FFLAG_DIRECT },
1227*0daf62d9SStanislav Sedov 		{ O_EXCL, PS_FST_FFLAG_EXCL },
1228*0daf62d9SStanislav Sedov 		{ O_EXEC, PS_FST_FFLAG_EXEC },
1229*0daf62d9SStanislav Sedov 		{ O_EXLOCK, PS_FST_FFLAG_EXLOCK },
1230*0daf62d9SStanislav Sedov 		{ O_NOFOLLOW, PS_FST_FFLAG_NOFOLLOW },
1231*0daf62d9SStanislav Sedov 		{ O_NONBLOCK, PS_FST_FFLAG_NONBLOCK },
1232*0daf62d9SStanislav Sedov 		{ O_SHLOCK, PS_FST_FFLAG_SHLOCK },
1233*0daf62d9SStanislav Sedov 		{ O_SYNC, PS_FST_FFLAG_SYNC },
1234*0daf62d9SStanislav Sedov 		{ O_TRUNC, PS_FST_FFLAG_TRUNC }
1235*0daf62d9SStanislav Sedov 	};
1236*0daf62d9SStanislav Sedov #define NFSTFLAGS	(sizeof(fstflags) / sizeof(*fstflags))
1237*0daf62d9SStanislav Sedov 	int fst_flags;
1238*0daf62d9SStanislav Sedov 	unsigned int i;
1239*0daf62d9SStanislav Sedov 
1240*0daf62d9SStanislav Sedov 	fst_flags = 0;
1241*0daf62d9SStanislav Sedov 	for (i = 0; i < NFSTFLAGS; i++)
1242*0daf62d9SStanislav Sedov 		if (flags & fstflags[i].flag)
1243*0daf62d9SStanislav Sedov 			fst_flags |= fstflags[i].fst_flag;
1244*0daf62d9SStanislav Sedov 	return (fst_flags);
1245*0daf62d9SStanislav Sedov }
1246*0daf62d9SStanislav Sedov 
1247*0daf62d9SStanislav Sedov /*
1248*0daf62d9SStanislav Sedov  * Vnode type to filestate translation.
1249*0daf62d9SStanislav Sedov  */
1250*0daf62d9SStanislav Sedov static int
1251*0daf62d9SStanislav Sedov vntype2psfsttype(int type)
1252*0daf62d9SStanislav Sedov {
1253*0daf62d9SStanislav Sedov 	static struct {
1254*0daf62d9SStanislav Sedov 		int	vtype;
1255*0daf62d9SStanislav Sedov 		int	fst_vtype;
1256*0daf62d9SStanislav Sedov 	} vt2fst[] = {
1257*0daf62d9SStanislav Sedov 		{ VBAD, PS_FST_VTYPE_VBAD },
1258*0daf62d9SStanislav Sedov 		{ VBLK, PS_FST_VTYPE_VBLK },
1259*0daf62d9SStanislav Sedov 		{ VCHR, PS_FST_VTYPE_VCHR },
1260*0daf62d9SStanislav Sedov 		{ VDIR, PS_FST_VTYPE_VDIR },
1261*0daf62d9SStanislav Sedov 		{ VFIFO, PS_FST_VTYPE_VFIFO },
1262*0daf62d9SStanislav Sedov 		{ VLNK, PS_FST_VTYPE_VLNK },
1263*0daf62d9SStanislav Sedov 		{ VNON, PS_FST_VTYPE_VNON },
1264*0daf62d9SStanislav Sedov 		{ VREG, PS_FST_VTYPE_VREG },
1265*0daf62d9SStanislav Sedov 		{ VSOCK, PS_FST_VTYPE_VSOCK }
1266*0daf62d9SStanislav Sedov 	};
1267*0daf62d9SStanislav Sedov #define	NVFTYPES	(sizeof(vt2fst) / sizeof(*vt2fst))
1268*0daf62d9SStanislav Sedov 	unsigned int i, fst_type;
1269*0daf62d9SStanislav Sedov 
1270*0daf62d9SStanislav Sedov 	fst_type = PS_FST_VTYPE_UNKNOWN;
1271*0daf62d9SStanislav Sedov 	for (i = 0; i < NVFTYPES; i++) {
1272*0daf62d9SStanislav Sedov 		if (type == vt2fst[i].vtype) {
1273*0daf62d9SStanislav Sedov 			fst_type = vt2fst[i].fst_vtype;
1274*0daf62d9SStanislav Sedov 			break;
1275*0daf62d9SStanislav Sedov 		}
1276*0daf62d9SStanislav Sedov 	}
1277*0daf62d9SStanislav Sedov 	return (fst_type);
1278*0daf62d9SStanislav Sedov }
1279*0daf62d9SStanislav Sedov 
1280*0daf62d9SStanislav Sedov static char *
1281*0daf62d9SStanislav Sedov getmnton(kvm_t *kd, struct mount *m)
1282*0daf62d9SStanislav Sedov {
1283*0daf62d9SStanislav Sedov 	static struct mount mnt;
1284*0daf62d9SStanislav Sedov 	static struct mtab {
1285*0daf62d9SStanislav Sedov 		struct mtab *next;
1286*0daf62d9SStanislav Sedov 		struct mount *m;
1287*0daf62d9SStanislav Sedov 		char mntonname[MNAMELEN + 1];
1288*0daf62d9SStanislav Sedov 	} *mhead = NULL;
1289*0daf62d9SStanislav Sedov 	struct mtab *mt;
1290*0daf62d9SStanislav Sedov 
1291*0daf62d9SStanislav Sedov 	for (mt = mhead; mt != NULL; mt = mt->next)
1292*0daf62d9SStanislav Sedov 		if (m == mt->m)
1293*0daf62d9SStanislav Sedov 			return (mt->mntonname);
1294*0daf62d9SStanislav Sedov 	if (!kvm_read_all(kd, (unsigned long)m, &mnt, sizeof(struct mount))) {
1295*0daf62d9SStanislav Sedov 		warnx("can't read mount table at %p", (void *)m);
1296*0daf62d9SStanislav Sedov 		return (NULL);
1297*0daf62d9SStanislav Sedov 	}
1298*0daf62d9SStanislav Sedov 	if ((mt = malloc(sizeof (struct mtab))) == NULL)
1299*0daf62d9SStanislav Sedov 		err(1, NULL);
1300*0daf62d9SStanislav Sedov 	mt->m = m;
1301*0daf62d9SStanislav Sedov 	bcopy(&mnt.mnt_stat.f_mntonname[0], &mt->mntonname[0], MNAMELEN);
1302*0daf62d9SStanislav Sedov 	mnt.mnt_stat.f_mntonname[MNAMELEN] = '\0';
1303*0daf62d9SStanislav Sedov 	mt->next = mhead;
1304*0daf62d9SStanislav Sedov 	mhead = mt;
1305*0daf62d9SStanislav Sedov 	return (mt->mntonname);
1306*0daf62d9SStanislav Sedov }
1307