#include #include #include #include #include #include #include "info.h" #define LEN 20 #define MNT_IGNORE 0 /* Internal Declarations */ static size_t regetmntinfo(struct statfs **mntbufp, long mntsize, const char **vfslist); static const char **makevfslist(char *fslist); static int checkvfsname(const char *vfsname, const char **vfslist); static char *makenetvfslist(void); static int skipvfs; /* Get information */ const char *get_os_type(void) { char *buf; size_t len; int mib[2]; mib[0] = CTL_KERN; mib[1] = KERN_OSTYPE; buf = malloc(LEN); len = LEN; if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) { // At this point `len` is _most likely_ set to `0` (e.g. in case of ENOMEM). // We copy our string and reset the length. strncpy(buf, "Darwin", LEN); len = LEN; } // Ensure null termination at the end. buf[len-1] = '\0'; return buf; } const char *get_os_release(void) { char *buf; size_t len; int mib[2]; mib[0] = CTL_KERN; mib[1] = KERN_OSRELEASE; buf = malloc(LEN); len = LEN; if (sysctl(mib, 2, buf, &len, NULL, 0) == -1) { // At this point `len` is _most likely_ set to `0` (e.g. in case of ENOMEM). // We copy our string and reset the length. strncpy(buf, "Unknown", LEN); len = LEN; } // Ensure null termination at the end. buf[len-1] = '\0'; return buf; } unsigned int get_cpu_num(void) { unsigned int num; int mib[2]; size_t len; mib[0] = CTL_HW; mib[1] = HW_NCPU; len = sizeof(num); if (sysctl(mib, 2, &num, &len, NULL, 0) == -1 || !len) num = 1; return num; } unsigned long get_cpu_speed(void) { unsigned long speed; size_t len; len = sizeof(speed); sysctlbyname("hw.cpufrequency", &speed, &len, NULL, 0); speed /= 1000000; return speed; } unsigned long get_proc_total(void) { int mib[3]; size_t len; mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_ALL; sysctl(mib, 3, NULL, &len, NULL, 0); return len / sizeof(struct kinfo_proc); } MemInfo get_mem_info(void) { static unsigned long long size = 0; size_t len; int mib[2]; vm_statistics_data_t vm_stat; struct xsw_usage swap_info; mach_msg_type_number_t count = HOST_VM_INFO_COUNT; MemInfo mi; if (size == 0) { mib[0] = CTL_HW; mib[1] = HW_MEMSIZE; len = sizeof(size); sysctl(mib, 2, &size, &len, NULL, 0); size /= 1024; } mib[0] = CTL_VM; mib[1] = VM_SWAPUSAGE; len = sizeof(swap_info); sysctl(mib, 2 , &swap_info, &len, NULL, 0); host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stat, &count); mi.total = size; mi.avail = (vm_stat.free_count + vm_stat.inactive_count) * PAGE_SIZE / 1024; mi.free = (vm_stat.free_count - vm_stat.speculative_count) * PAGE_SIZE / 1024; mi.buffers = 0; mi.cached = 0; mi.swap_total = swap_info.xsu_total / 1024; mi.swap_free = swap_info.xsu_avail / 1024; return mi; } DiskInfo get_disk_info(void) { DiskInfo di; struct statfs *mntbuf; const char **vfslist; char *str; size_t i, mntsize; size_t used, availblks; const double reported_units = 1e9; float pct; float most_full = 0.0; double toru, dtotal = 0.0, dfree = 0.0; str = makenetvfslist(); vfslist = makevfslist(str); free(str); mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); mntsize = regetmntinfo(&mntbuf, mntsize, vfslist); for (i = 0; i < mntsize; i++) { if ((mntbuf[i].f_flags & MNT_IGNORE) == 0) { used = mntbuf[i].f_blocks - mntbuf[i].f_bfree; availblks = mntbuf[i].f_bavail + used; pct = (availblks == 0 ? 100.0 : (double)used / (double)availblks * 100.0); if (pct > most_full) most_full = pct; toru = reported_units / mntbuf[i].f_bsize; dtotal += mntbuf[i].f_blocks / toru; dfree += mntbuf[i].f_bavail / toru; } } free(vfslist); di.total = dtotal * 1000000; di.free = dfree * 1000000; return di; } /* Internal definitions */ const char **makevfslist(char *fslist) { const char **av; int i; char *nextcp; if (fslist == NULL) return (NULL); if (fslist[0] == 'n' && fslist[1] == 'o') { fslist += 2; skipvfs = 1; } for (i = 0, nextcp = fslist; *nextcp; nextcp++) if (*nextcp == ',') i++; if ((av = (const char**)malloc((size_t)(i + 2) * sizeof(char *))) == NULL) { return (NULL); } nextcp = fslist; i = 0; av[i++] = nextcp; while ((nextcp = strchr(nextcp, ',')) != NULL) { *nextcp++ = '\0'; av[i++] = nextcp; } av[i++] = NULL; return (av); } size_t regetmntinfo(struct statfs **mntbufp, long mntsize, const char **vfslist) { int i, j; struct statfs *mntbuf; if (vfslist == NULL) return (getmntinfo(mntbufp, MNT_WAIT)); mntbuf = *mntbufp; for (j = 0, i = 0; i < mntsize; i++) { if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) continue; (void)statfs(mntbuf[i].f_mntonname,&mntbuf[j]); j++; } return (j); } int checkvfsname(const char *vfsname, const char **vfslist) { if (vfslist == NULL) return (0); while (*vfslist != NULL) { if (strcmp(vfsname, *vfslist) == 0) return (skipvfs); ++vfslist; } return (!skipvfs); } char *makenetvfslist(void){ char *str, *strptr, **listptr; int mib[4], maxvfsconf, cnt=0, i; size_t miblen; struct vfsconf vfc; mib[0] = CTL_VFS; mib[1] = VFS_GENERIC; mib[2] = VFS_MAXTYPENUM; miblen=sizeof(maxvfsconf); if (sysctl(mib, 3, &maxvfsconf, &miblen, NULL, 0)) { return (NULL); } if ((listptr = (char**)malloc(sizeof(char*)*maxvfsconf)) == NULL) { return (NULL); } miblen = sizeof (struct vfsconf); mib[2] = VFS_CONF; for (i = 0; i < maxvfsconf; i++) { mib[3] = i; if (sysctl(mib, 4, &vfc, &miblen, NULL, 0) == 0) { if (!(vfc.vfc_flags & MNT_LOCAL)) { listptr[cnt++] = strdup(vfc.vfc_name); if (listptr[cnt-1] == NULL) { return (NULL); } } } } if (cnt == 0 || (str = (char*)malloc(sizeof(char) * (32 * cnt + cnt + 2))) == NULL) { free(listptr); return (NULL); } *str = 'n'; *(str + 1) = 'o'; for (i = 0, strptr = str + 2; i < cnt; i++, strptr++) { strncpy(strptr, listptr[i], 32); strptr += strlen(listptr[i]); *strptr = ','; free(listptr[i]); } *(--strptr) = '\0'; free(listptr); return (str); }