143151ee6SPeter Wemm #include <sys/cdefs.h>
2aa334e41SRobert Watson #include <sys/param.h>
343151ee6SPeter Wemm #include <sys/sysctl.h>
47adf46f0SEnji Cooper #include <sys/user.h>
543151ee6SPeter Wemm #include <stdlib.h>
643151ee6SPeter Wemm #include <string.h>
743151ee6SPeter Wemm
843151ee6SPeter Wemm #include "libutil.h"
943151ee6SPeter Wemm
1043151ee6SPeter Wemm struct kinfo_file *
kinfo_getfile(pid_t pid,int * cntp)1143151ee6SPeter Wemm kinfo_getfile(pid_t pid, int *cntp)
1243151ee6SPeter Wemm {
1343151ee6SPeter Wemm int mib[4];
1443151ee6SPeter Wemm int error;
1543151ee6SPeter Wemm int cnt;
1643151ee6SPeter Wemm size_t len;
1743151ee6SPeter Wemm char *buf, *bp, *eb;
1843151ee6SPeter Wemm struct kinfo_file *kif, *kp, *kf;
1943151ee6SPeter Wemm
206c3b8117SJoe Marcus Clarke *cntp = 0;
2143151ee6SPeter Wemm len = 0;
2243151ee6SPeter Wemm mib[0] = CTL_KERN;
2343151ee6SPeter Wemm mib[1] = KERN_PROC;
2443151ee6SPeter Wemm mib[2] = KERN_PROC_FILEDESC;
2543151ee6SPeter Wemm mib[3] = pid;
2643151ee6SPeter Wemm
277adf46f0SEnji Cooper error = sysctl(mib, nitems(mib), NULL, &len, NULL, 0);
2843151ee6SPeter Wemm if (error)
296c3b8117SJoe Marcus Clarke return (NULL);
30*4b60fac3SEd Maste /*
31*4b60fac3SEd Maste * Add extra space as the table may grow between requesting the size
32*4b60fac3SEd Maste * and fetching the data.
33*4b60fac3SEd Maste */
3443151ee6SPeter Wemm len = len * 4 / 3;
3543151ee6SPeter Wemm buf = malloc(len);
3643151ee6SPeter Wemm if (buf == NULL)
376c3b8117SJoe Marcus Clarke return (NULL);
387adf46f0SEnji Cooper error = sysctl(mib, nitems(mib), buf, &len, NULL, 0);
3943151ee6SPeter Wemm if (error) {
4043151ee6SPeter Wemm free(buf);
416c3b8117SJoe Marcus Clarke return (NULL);
4243151ee6SPeter Wemm }
4343151ee6SPeter Wemm /* Pass 1: count items */
4443151ee6SPeter Wemm cnt = 0;
4543151ee6SPeter Wemm bp = buf;
4643151ee6SPeter Wemm eb = buf + len;
4743151ee6SPeter Wemm while (bp < eb) {
48de94a63bSPeter Wemm kf = (struct kinfo_file *)(uintptr_t)bp;
4914bdbaf2SConrad Meyer if (kf->kf_structsize == 0)
5014bdbaf2SConrad Meyer break;
5143151ee6SPeter Wemm bp += kf->kf_structsize;
5243151ee6SPeter Wemm cnt++;
5343151ee6SPeter Wemm }
5443151ee6SPeter Wemm
5543151ee6SPeter Wemm kif = calloc(cnt, sizeof(*kif));
5643151ee6SPeter Wemm if (kif == NULL) {
5743151ee6SPeter Wemm free(buf);
586c3b8117SJoe Marcus Clarke return (NULL);
5943151ee6SPeter Wemm }
6043151ee6SPeter Wemm bp = buf;
6143151ee6SPeter Wemm eb = buf + len;
6243151ee6SPeter Wemm kp = kif;
6343151ee6SPeter Wemm /* Pass 2: unpack */
6443151ee6SPeter Wemm while (bp < eb) {
65de94a63bSPeter Wemm kf = (struct kinfo_file *)(uintptr_t)bp;
6614bdbaf2SConrad Meyer if (kf->kf_structsize == 0)
6714bdbaf2SConrad Meyer break;
6843151ee6SPeter Wemm /* Copy/expand into pre-zeroed buffer */
6943151ee6SPeter Wemm memcpy(kp, kf, kf->kf_structsize);
7043151ee6SPeter Wemm /* Advance to next packed record */
7143151ee6SPeter Wemm bp += kf->kf_structsize;
7243151ee6SPeter Wemm /* Set field size to fixed length, advance */
7343151ee6SPeter Wemm kp->kf_structsize = sizeof(*kp);
7443151ee6SPeter Wemm kp++;
7543151ee6SPeter Wemm }
7643151ee6SPeter Wemm free(buf);
7743151ee6SPeter Wemm *cntp = cnt;
7843151ee6SPeter Wemm return (kif); /* Caller must free() return value */
7943151ee6SPeter Wemm }
80