xref: /freebsd/lib/libutil/kinfo_getfile.c (revision 14bdbaf2e40a827e84f6c2fe27b1f8229767f03c)
143151ee6SPeter Wemm #include <sys/cdefs.h>
243151ee6SPeter Wemm __FBSDID("$FreeBSD$");
343151ee6SPeter Wemm 
4aa334e41SRobert Watson #include <sys/param.h>
543151ee6SPeter Wemm #include <sys/user.h>
643151ee6SPeter Wemm #include <sys/sysctl.h>
743151ee6SPeter Wemm #include <stdlib.h>
843151ee6SPeter Wemm #include <string.h>
943151ee6SPeter Wemm 
1043151ee6SPeter Wemm #include "libutil.h"
1143151ee6SPeter Wemm 
1243151ee6SPeter Wemm struct kinfo_file *
1343151ee6SPeter Wemm kinfo_getfile(pid_t pid, int *cntp)
1443151ee6SPeter Wemm {
1543151ee6SPeter Wemm 	int mib[4];
1643151ee6SPeter Wemm 	int error;
1743151ee6SPeter Wemm 	int cnt;
1843151ee6SPeter Wemm 	size_t len;
1943151ee6SPeter Wemm 	char *buf, *bp, *eb;
2043151ee6SPeter Wemm 	struct kinfo_file *kif, *kp, *kf;
2143151ee6SPeter Wemm 
226c3b8117SJoe Marcus Clarke 	*cntp = 0;
2343151ee6SPeter Wemm 	len = 0;
2443151ee6SPeter Wemm 	mib[0] = CTL_KERN;
2543151ee6SPeter Wemm 	mib[1] = KERN_PROC;
2643151ee6SPeter Wemm 	mib[2] = KERN_PROC_FILEDESC;
2743151ee6SPeter Wemm 	mib[3] = pid;
2843151ee6SPeter Wemm 
2943151ee6SPeter Wemm 	error = sysctl(mib, 4, NULL, &len, NULL, 0);
3043151ee6SPeter Wemm 	if (error)
316c3b8117SJoe Marcus Clarke 		return (NULL);
3243151ee6SPeter Wemm 	len = len * 4 / 3;
3343151ee6SPeter Wemm 	buf = malloc(len);
3443151ee6SPeter Wemm 	if (buf == NULL)
356c3b8117SJoe Marcus Clarke 		return (NULL);
3643151ee6SPeter Wemm 	error = sysctl(mib, 4, buf, &len, NULL, 0);
3743151ee6SPeter Wemm 	if (error) {
3843151ee6SPeter Wemm 		free(buf);
396c3b8117SJoe Marcus Clarke 		return (NULL);
4043151ee6SPeter Wemm 	}
4143151ee6SPeter Wemm 	/* Pass 1: count items */
4243151ee6SPeter Wemm 	cnt = 0;
4343151ee6SPeter Wemm 	bp = buf;
4443151ee6SPeter Wemm 	eb = buf + len;
4543151ee6SPeter Wemm 	while (bp < eb) {
46de94a63bSPeter Wemm 		kf = (struct kinfo_file *)(uintptr_t)bp;
47*14bdbaf2SConrad Meyer 		if (kf->kf_structsize == 0)
48*14bdbaf2SConrad Meyer 			break;
4943151ee6SPeter Wemm 		bp += kf->kf_structsize;
5043151ee6SPeter Wemm 		cnt++;
5143151ee6SPeter Wemm 	}
5243151ee6SPeter Wemm 
5343151ee6SPeter Wemm 	kif = calloc(cnt, sizeof(*kif));
5443151ee6SPeter Wemm 	if (kif == NULL) {
5543151ee6SPeter Wemm 		free(buf);
566c3b8117SJoe Marcus Clarke 		return (NULL);
5743151ee6SPeter Wemm 	}
5843151ee6SPeter Wemm 	bp = buf;
5943151ee6SPeter Wemm 	eb = buf + len;
6043151ee6SPeter Wemm 	kp = kif;
6143151ee6SPeter Wemm 	/* Pass 2: unpack */
6243151ee6SPeter Wemm 	while (bp < eb) {
63de94a63bSPeter Wemm 		kf = (struct kinfo_file *)(uintptr_t)bp;
64*14bdbaf2SConrad Meyer 		if (kf->kf_structsize == 0)
65*14bdbaf2SConrad Meyer 			break;
6643151ee6SPeter Wemm 		/* Copy/expand into pre-zeroed buffer */
6743151ee6SPeter Wemm 		memcpy(kp, kf, kf->kf_structsize);
6843151ee6SPeter Wemm 		/* Advance to next packed record */
6943151ee6SPeter Wemm 		bp += kf->kf_structsize;
7043151ee6SPeter Wemm 		/* Set field size to fixed length, advance */
7143151ee6SPeter Wemm 		kp->kf_structsize = sizeof(*kp);
7243151ee6SPeter Wemm 		kp++;
7343151ee6SPeter Wemm 	}
7443151ee6SPeter Wemm 	free(buf);
7543151ee6SPeter Wemm 	*cntp = cnt;
7643151ee6SPeter Wemm 	return (kif);	/* Caller must free() return value */
7743151ee6SPeter Wemm }
78