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