1 #include <sys/cdefs.h> 2 #include <sys/param.h> 3 #include <sys/sysctl.h> 4 #include <sys/user.h> 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include "libutil.h" 9 10 struct kinfo_file * 11 kinfo_getfile(pid_t pid, int *cntp) 12 { 13 int mib[4]; 14 int error; 15 int cnt; 16 size_t len; 17 char *buf, *bp, *eb; 18 struct kinfo_file *kif, *kp, *kf; 19 20 *cntp = 0; 21 len = 0; 22 mib[0] = CTL_KERN; 23 mib[1] = KERN_PROC; 24 mib[2] = KERN_PROC_FILEDESC; 25 mib[3] = pid; 26 27 error = sysctl(mib, nitems(mib), NULL, &len, NULL, 0); 28 if (error) 29 return (NULL); 30 /* 31 * Add extra space as the table may grow between requesting the size 32 * and fetching the data. 33 */ 34 len = len * 4 / 3; 35 buf = malloc(len); 36 if (buf == NULL) 37 return (NULL); 38 error = sysctl(mib, nitems(mib), buf, &len, NULL, 0); 39 if (error) { 40 free(buf); 41 return (NULL); 42 } 43 /* Pass 1: count items */ 44 cnt = 0; 45 bp = buf; 46 eb = buf + len; 47 while (bp < eb) { 48 kf = (struct kinfo_file *)(uintptr_t)bp; 49 if (kf->kf_structsize == 0) 50 break; 51 bp += kf->kf_structsize; 52 cnt++; 53 } 54 55 kif = calloc(cnt, sizeof(*kif)); 56 if (kif == NULL) { 57 free(buf); 58 return (NULL); 59 } 60 bp = buf; 61 eb = buf + len; 62 kp = kif; 63 /* Pass 2: unpack */ 64 while (bp < eb) { 65 kf = (struct kinfo_file *)(uintptr_t)bp; 66 if (kf->kf_structsize == 0) 67 break; 68 /* Copy/expand into pre-zeroed buffer */ 69 memcpy(kp, kf, kf->kf_structsize); 70 /* Advance to next packed record */ 71 bp += kf->kf_structsize; 72 /* Set field size to fixed length, advance */ 73 kp->kf_structsize = sizeof(*kp); 74 kp++; 75 } 76 free(buf); 77 *cntp = cnt; 78 return (kif); /* Caller must free() return value */ 79 } 80