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