xref: /f-stack/tools/libutil/kinfo_getfile.c (revision 22ce4aff)
11eaf0ac3Slogwang #include <sys/cdefs.h>
21eaf0ac3Slogwang __FBSDID("$FreeBSD$");
31eaf0ac3Slogwang 
41eaf0ac3Slogwang #include <sys/param.h>
51eaf0ac3Slogwang #include <sys/sysctl.h>
6*22ce4affSfengbojiang #include <sys/user.h>
71eaf0ac3Slogwang #include <stdlib.h>
81eaf0ac3Slogwang #include <string.h>
91eaf0ac3Slogwang 
101eaf0ac3Slogwang #include "libutil.h"
111eaf0ac3Slogwang 
121eaf0ac3Slogwang struct kinfo_file *
kinfo_getfile(pid_t pid,int * cntp)131eaf0ac3Slogwang kinfo_getfile(pid_t pid, int *cntp)
141eaf0ac3Slogwang {
151eaf0ac3Slogwang 	int mib[4];
161eaf0ac3Slogwang 	int error;
171eaf0ac3Slogwang 	int cnt;
181eaf0ac3Slogwang 	size_t len;
191eaf0ac3Slogwang 	char *buf, *bp, *eb;
201eaf0ac3Slogwang 	struct kinfo_file *kif, *kp, *kf;
211eaf0ac3Slogwang 
221eaf0ac3Slogwang 	*cntp = 0;
231eaf0ac3Slogwang 	len = 0;
241eaf0ac3Slogwang 	mib[0] = CTL_KERN;
251eaf0ac3Slogwang 	mib[1] = KERN_PROC;
261eaf0ac3Slogwang 	mib[2] = KERN_PROC_FILEDESC;
271eaf0ac3Slogwang 	mib[3] = pid;
281eaf0ac3Slogwang 
29*22ce4affSfengbojiang 	error = sysctl(mib, nitems(mib), NULL, &len, NULL, 0);
301eaf0ac3Slogwang 	if (error)
311eaf0ac3Slogwang 		return (NULL);
321eaf0ac3Slogwang 	len = len * 4 / 3;
331eaf0ac3Slogwang 	buf = malloc(len);
341eaf0ac3Slogwang 	if (buf == NULL)
351eaf0ac3Slogwang 		return (NULL);
36*22ce4affSfengbojiang 	error = sysctl(mib, nitems(mib), buf, &len, NULL, 0);
371eaf0ac3Slogwang 	if (error) {
381eaf0ac3Slogwang 		free(buf);
391eaf0ac3Slogwang 		return (NULL);
401eaf0ac3Slogwang 	}
411eaf0ac3Slogwang 	/* Pass 1: count items */
421eaf0ac3Slogwang 	cnt = 0;
431eaf0ac3Slogwang 	bp = buf;
441eaf0ac3Slogwang 	eb = buf + len;
451eaf0ac3Slogwang 	while (bp < eb) {
461eaf0ac3Slogwang 		kf = (struct kinfo_file *)(uintptr_t)bp;
471eaf0ac3Slogwang 		if (kf->kf_structsize == 0)
481eaf0ac3Slogwang 			break;
491eaf0ac3Slogwang 		bp += kf->kf_structsize;
501eaf0ac3Slogwang 		cnt++;
511eaf0ac3Slogwang 	}
521eaf0ac3Slogwang 
531eaf0ac3Slogwang 	kif = calloc(cnt, sizeof(*kif));
541eaf0ac3Slogwang 	if (kif == NULL) {
551eaf0ac3Slogwang 		free(buf);
561eaf0ac3Slogwang 		return (NULL);
571eaf0ac3Slogwang 	}
581eaf0ac3Slogwang 	bp = buf;
591eaf0ac3Slogwang 	eb = buf + len;
601eaf0ac3Slogwang 	kp = kif;
611eaf0ac3Slogwang 	/* Pass 2: unpack */
621eaf0ac3Slogwang 	while (bp < eb) {
631eaf0ac3Slogwang 		kf = (struct kinfo_file *)(uintptr_t)bp;
641eaf0ac3Slogwang 		if (kf->kf_structsize == 0)
651eaf0ac3Slogwang 			break;
661eaf0ac3Slogwang 		/* Copy/expand into pre-zeroed buffer */
671eaf0ac3Slogwang 		memcpy(kp, kf, kf->kf_structsize);
681eaf0ac3Slogwang 		/* Advance to next packed record */
691eaf0ac3Slogwang 		bp += kf->kf_structsize;
701eaf0ac3Slogwang 		/* Set field size to fixed length, advance */
711eaf0ac3Slogwang 		kp->kf_structsize = sizeof(*kp);
721eaf0ac3Slogwang 		kp++;
731eaf0ac3Slogwang 	}
741eaf0ac3Slogwang 	free(buf);
751eaf0ac3Slogwang 	*cntp = cnt;
761eaf0ac3Slogwang 	return (kif);	/* Caller must free() return value */
771eaf0ac3Slogwang }
78