kinfo_getfile.c revision 185548
1#include <sys/cdefs.h>
2__FBSDID("$FreeBSD: head/lib/libutil/kinfo_getfile.c 185548 2008-12-02 06:50:26Z peter $");
3
4#include <sys/types.h>
5#include <sys/user.h>
6#include <sys/sysctl.h>
7#include <stdlib.h>
8#include <string.h>
9
10#include "libutil.h"
11
12struct kinfo_file *
13kinfo_getfile(pid_t pid, int *cntp)
14{
15	int mib[4];
16	int error;
17	int cnt;
18	size_t len;
19	char *buf, *bp, *eb;
20	struct kinfo_file *kif, *kp, *kf;
21
22	len = 0;
23	mib[0] = CTL_KERN;
24	mib[1] = KERN_PROC;
25	mib[2] = KERN_PROC_FILEDESC;
26	mib[3] = pid;
27
28	error = sysctl(mib, 4, NULL, &len, NULL, 0);
29	if (error)
30		return (0);
31	len = len * 4 / 3;
32	buf = malloc(len);
33	if (buf == NULL)
34		return (0);
35	error = sysctl(mib, 4, buf, &len, NULL, 0);
36	if (error) {
37		free(buf);
38		return (0);
39	}
40	/* Pass 1: count items */
41	cnt = 0;
42	bp = buf;
43	eb = buf + len;
44	while (bp < eb) {
45		kf = (struct kinfo_file *)bp;
46		bp += kf->kf_structsize;
47		cnt++;
48	}
49
50	kif = calloc(cnt, sizeof(*kif));
51	if (kif == NULL) {
52		free(buf);
53		return (0);
54	}
55	bp = buf;
56	eb = buf + len;
57	kp = kif;
58	/* Pass 2: unpack */
59	while (bp < eb) {
60		kf = (struct kinfo_file *)bp;
61		/* Copy/expand into pre-zeroed buffer */
62		memcpy(kp, kf, kf->kf_structsize);
63		/* Advance to next packed record */
64		bp += kf->kf_structsize;
65		/* Set field size to fixed length, advance */
66		kp->kf_structsize = sizeof(*kp);
67		kp++;
68	}
69	free(buf);
70	*cntp = cnt;
71	return (kif);	/* Caller must free() return value */
72}
73