]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - lib/libutil/kinfo_getfile.c
MFC r347990:
[FreeBSD/stable/10.git] / lib / libutil / kinfo_getfile.c
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 *
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 }