kinfo_getfile.c revision 185553
19313Ssos#include <sys/cdefs.h>
29313Ssos__FBSDID("$FreeBSD: head/lib/libutil/kinfo_getfile.c 185553 2008-12-02 10:10:50Z peter $");
39313Ssos
49313Ssos#include <sys/types.h>
59313Ssos#include <sys/user.h>
69313Ssos#include <sys/sysctl.h>
79313Ssos#include <stdlib.h>
89313Ssos#include <string.h>
9111798Sdes
109313Ssos#include "libutil.h"
119313Ssos
129313Ssosstruct kinfo_file *
139313Ssoskinfo_getfile(pid_t pid, int *cntp)
149313Ssos{
1597748Sschweikh	int mib[4];
169313Ssos	int error;
179313Ssos	int cnt;
189313Ssos	size_t len;
199313Ssos	char *buf, *bp, *eb;
209313Ssos	struct kinfo_file *kif, *kp, *kf;
219313Ssos
229313Ssos	len = 0;
239313Ssos	mib[0] = CTL_KERN;
249313Ssos	mib[1] = KERN_PROC;
259313Ssos	mib[2] = KERN_PROC_FILEDESC;
269313Ssos	mib[3] = pid;
279313Ssos
289313Ssos	error = sysctl(mib, 4, NULL, &len, NULL, 0);
29116173Sobrien	if (error)
30116173Sobrien		return (0);
31116173Sobrien	len = len * 4 / 3;
32156874Sru	buf = malloc(len);
33101189Srwatson	if (buf == NULL)
3431784Seivind		return (0);
359313Ssos	error = sysctl(mib, 4, buf, &len, NULL, 0);
369313Ssos	if (error) {
3776166Smarkm		free(buf);
3876166Smarkm		return (0);
399313Ssos	}
409313Ssos	/* Pass 1: count items */
419313Ssos	cnt = 0;
4231561Sbde	bp = buf;
439313Ssos	eb = buf + len;
4472538Sjlemon	while (bp < eb) {
4576166Smarkm		kf = (struct kinfo_file *)(uintptr_t)bp;
46168014Sjulian		bp += kf->kf_structsize;
4776166Smarkm		cnt++;
48162201Snetchild	}
49166085Skib
50102814Siedowse	kif = calloc(cnt, sizeof(*kif));
5176166Smarkm	if (kif == NULL) {
5214331Speter		free(buf);
53162585Snetchild		return (0);
5476166Smarkm	}
5512458Sbde	bp = buf;
56163606Srwatson	eb = buf + len;
57163606Srwatson	kp = kif;
5872538Sjlemon	/* Pass 2: unpack */
5972538Sjlemon	while (bp < eb) {
6072538Sjlemon		kf = (struct kinfo_file *)(uintptr_t)bp;
6172538Sjlemon		/* Copy/expand into pre-zeroed buffer */
62140214Sobrien		memcpy(kp, kf, kf->kf_structsize);
63140214Sobrien		/* Advance to next packed record */
64140214Sobrien		bp += kf->kf_structsize;
65140214Sobrien		/* Set field size to fixed length, advance */
6664905Smarcel		kp->kf_structsize = sizeof(*kp);
6768583Smarcel		kp++;
68133816Stjr	}
6964905Smarcel	free(buf);
709313Ssos	*cntp = cnt;
719313Ssos	return (kif);	/* Caller must free() return value */
7283366Sjulian}
739313Ssos