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