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 } 78