kinfo_getfile.c revision 185493
1185493Speter#include <sys/cdefs.h>
2185493Speter__FBSDID("$FreeBSD: user/peter/kinfo/lib/libutil/kinfo_getfile.c 185493 2008-11-30 22:40:14Z peter $");
3185493Speter
4185493Speter#include <sys/types.h>
5185493Speter#include <sys/user.h>
6185493Speter#include <sys/sysctl.h>
7185493Speter#include <stdlib.h>
8185493Speter#include <string.h>
9185493Speter
10185493Speter#include "libutil.h"
11185493Speter
12185493Speterstruct kinfo_file *
13185493Speterkinfo_getfile(pid_t pid, int *cntp)
14185493Speter{
15185493Speter	int mib[4];
16185493Speter	int error;
17185493Speter	int cnt;
18185493Speter	size_t len;
19185493Speter	char *buf, *bp, *eb;
20185493Speter	struct kinfo_file *kif, *kp, *kf;
21185493Speter
22185493Speter	len = 0;
23185493Speter	mib[0] = CTL_KERN;
24185493Speter	mib[1] = KERN_PROC;
25185493Speter	mib[2] = KERN_PROC_FILEDESC;
26185493Speter	mib[3] = pid;
27185493Speter
28185493Speter	error = sysctl(mib, 4, NULL, &len, NULL, 0);
29185493Speter	if (error)
30185493Speter		return (0);
31185493Speter	len = len * 4 / 3;
32185493Speter	buf = malloc(len);
33185493Speter	if (buf == NULL)
34185493Speter		return (0);
35185493Speter	error = sysctl(mib, 4, buf, &len, NULL, 0);
36185493Speter	if (error) {
37185493Speter		free(buf);
38185493Speter		return (0);
39185493Speter	}
40185493Speter	/* Pass 1: count items */
41185493Speter	cnt = 0;
42185493Speter	bp = buf;
43185493Speter	eb = buf + len;
44185493Speter	while (bp < eb) {
45185493Speter		kf = (struct kinfo_file *)bp;
46185493Speter		bp += kf->kf_structsize;
47185493Speter		cnt++;
48185493Speter	}
49185493Speter
50185493Speter	kif = calloc(cnt, sizeof(*kif));
51185493Speter	if (kif == NULL) {
52185493Speter		free(buf);
53185493Speter		return (0);
54185493Speter	}
55185493Speter	bp = buf;
56185493Speter	eb = buf + len;
57185493Speter	kp = kif;
58185493Speter	/* Pass 2: unpack */
59185493Speter	while (bp < eb) {
60185493Speter		kf = (struct kinfo_file *)bp;
61185493Speter		/* Copy/expand into pre-zeroed buffer */
62185493Speter		memcpy(kp, kf, kf->kf_structsize);
63185493Speter		/* Advance to next packed record */
64185493Speter		bp += kf->kf_structsize;
65185493Speter		/* Set field size to fixed length, advance */
66185493Speter		kp->kf_structsize = sizeof(*kp);
67185493Speter		kp++;
68185493Speter	}
69185493Speter	free(buf);
70185493Speter	*cntp = cnt;
71185493Speter	return (kif);	/* Caller must free() return value */
72185493Speter}
73