]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libutil/kinfo_getvmmap.c
src.conf.5: Regen after removing MK_NVME
[FreeBSD/FreeBSD.git] / lib / libutil / kinfo_getvmmap.c
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_vmentry *
11 kinfo_getvmmap(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_vmentry *kiv, *kp, *kv;
19
20         *cntp = 0;
21         len = 0;
22         mib[0] = CTL_KERN;
23         mib[1] = KERN_PROC;
24         mib[2] = KERN_PROC_VMMAP;
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                 kv = (struct kinfo_vmentry *)(uintptr_t)bp;
45                 if (kv->kve_structsize == 0)
46                         break;
47                 bp += kv->kve_structsize;
48                 cnt++;
49         }
50
51         kiv = calloc(cnt, sizeof(*kiv));
52         if (kiv == NULL) {
53                 free(buf);
54                 return (NULL);
55         }
56         bp = buf;
57         eb = buf + len;
58         kp = kiv;
59         /* Pass 2: unpack */
60         while (bp < eb) {
61                 kv = (struct kinfo_vmentry *)(uintptr_t)bp;
62                 if (kv->kve_structsize == 0)
63                         break;
64                 /* Copy/expand into pre-zeroed buffer */
65                 memcpy(kp, kv, kv->kve_structsize);
66                 /* Advance to next packed record */
67                 bp += kv->kve_structsize;
68                 /* Set field size to fixed length, advance */
69                 kp->kve_structsize = sizeof(*kp);
70                 kp++;
71         }
72         free(buf);
73         *cntp = cnt;
74         return (kiv);   /* Caller must free() return value */
75 }