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