Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FreeBSD port. #60

Merged
merged 1 commit into from
May 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ fn main() {
println!("cargo:rustc-flags=-l psapi");
builder.file("c/windows.c")
},
"freebsd" => {
println!("cargo:rustc-flags=-l pthread");
builder.file("c/freebsd.c")
},
_ => panic!("unsupported system: {}", target_os)
};
builder.compile("info");
Expand Down
165 changes: 165 additions & 0 deletions c/freebsd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <sys/utsname.h>
#include <sys/vmmeter.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "info.h"

static const char *os_release;

static pthread_once_t once_init_freebsd;
static void init_freebsd(void) {
struct utsname un;

if (uname(&un) == -1)
return;
os_release = strdup(un.release);
}

const char *get_os_release(void) {
pthread_once(&once_init_freebsd, init_freebsd);
return (os_release);
}

unsigned long get_cpu_speed(void) {
uint64_t tsc_freq;
size_t len;
int error;

len = sizeof(tsc_freq);
error = sysctlbyname("machdep.tsc_freq", &tsc_freq, &len, NULL, 0);
if (error == -1)
return (1000);
return (tsc_freq / 1000 / 1000);
}

unsigned long get_proc_total(void) {
struct kinfo_proc *kp, *kpp;
int mib[3], count, error;
size_t len;

mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PROC;

error = sysctl(mib, nitems(mib), NULL, &len, NULL, 0);
if (error == -1)
return (42);

kp = malloc(len);
if (kp == NULL)
return (42);
memset(kp, 0, len);

error = sysctl(mib, nitems(mib), kp, &len, NULL, 0);
if (error == -1) {
free(kp);
return (42);
}

for (count = 0, kpp = kp; (char *)kpp < (char *)kp + len; kpp++) {
if (kpp->ki_pid == 0)
continue;
count++;
}
free(kp);
return (count);
}

MemInfo get_mem_info(void) {
struct MemInfo mi;
struct vmtotal vmt;
struct xswdev xs;
int mib[3], error, i;
unsigned long res;
size_t len;

len = sizeof(res);
error = sysctlbyname("hw.realmem", &res, &len, NULL, 0);
if (error == -1)
goto fail;
mi.total = res / 1024;

len = sizeof(res);
error = sysctlbyname("hw.physmem", &res, &len, NULL, 0);
if (error == -1)
goto fail;
mi.avail = res / 1024;

mib[0] = CTL_VM;
mib[1] = VM_TOTAL;
len = sizeof(vmt);
error = sysctl(mib, 2, &vmt, &len, NULL, 0);
if (error == -1)
goto fail;
mi.free = vmt.t_free * PAGE_SIZE / 1024;

mi.buffers = 0;
mi.cached = 0;

mi.swap_total = 0;
mi.swap_free = 0;
len = nitems(mib);
if (sysctlnametomib("vm.swap_info", mib, &len) == -1)
goto fail;
for (i = 0; ; i++) {
mib[2] = i;
len = sizeof(xs);
error = sysctl(mib, 3, &xs, &len, NULL, 0);
if (error == -1)
break;
mi.swap_total += (uint64_t)xs.xsw_nblks * PAGE_SIZE / 1024;
mi.swap_free += ((uint64_t)xs.xsw_nblks - xs.xsw_used) *
PAGE_SIZE / 1024;
}
return (mi);

fail:
memset(&mi, 0, sizeof(mi));
return (mi);
}

DiskInfo get_disk_info(void) {
DiskInfo di;
struct statfs *sfs, *sf;
int i, nmounts;
uint64_t dtotal, dfree;

di.total = 0;
di.free = 0;
dtotal = 0;
dfree = 0;
sfs = NULL;

nmounts = getfsstat(NULL, 0, MNT_WAIT);
if (nmounts == -1)
goto fail;
sfs = calloc(nmounts, sizeof(*sfs));
if (sfs == NULL)
goto fail;
nmounts = getfsstat(sfs, nmounts * sizeof(*sfs), MNT_WAIT);
if (nmounts == -1)
goto fail;

for (i = 0; i < nmounts; i++) {
sf = &sfs[i];
if ((sf->f_flags & (MNT_LOCAL | MNT_IGNORE)) != MNT_LOCAL)
continue;
dtotal += sf->f_blocks * sf->f_bsize;
dfree += sf->f_bfree * sf->f_bsize;
}

di.total = dtotal / 1000;
di.free = dfree / 1000;

fail:
free(sfs);
return (di);
}
66 changes: 35 additions & 31 deletions lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ use std::ffi;
use std::fmt;
use std::io::{self, Read};
use std::fs::File;
#[cfg(any(target_os = "windows", target_os = "macos"))]
#[cfg(any(target_os = "windows", target_os = "macos", target_os = "freebsd"))]
use std::os::raw::c_char;
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
use std::os::raw::{c_int, c_double};

#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
use libc::sysctl;
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
use std::mem::size_of_val;
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os = "freebsd"))]
use std::ptr::null_mut;
#[cfg(not(target_os = "windows"))]
use libc::timeval;
Expand All @@ -32,10 +32,10 @@ use std::collections::HashMap;
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
mod kstat;

#[cfg(target_os = "macos")]
static MAC_CTL_KERN: libc::c_int = 1;
#[cfg(target_os = "macos")]
static MAC_KERN_BOOTTIME: libc::c_int = 21;
#[cfg(any(target_os = "macos", target_os="freebsd"))]
static OS_CTL_KERN: libc::c_int = 1;
#[cfg(any(target_os = "macos", target_os="freebsd"))]
static OS_KERN_BOOTTIME: libc::c_int = 21;

/// System load average value.
#[repr(C)]
Expand Down Expand Up @@ -172,22 +172,22 @@ impl From<Box<dyn std::error::Error>> for Error {
extern "C" {
#[cfg(any(target_os = "macos", target_os = "windows"))]
fn get_os_type() -> *const i8;
#[cfg(any(target_os = "macos", target_os = "windows"))]
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd"))]
fn get_os_release() -> *const i8;

#[cfg(all(not(any(target_os = "solaris", target_os = "illumos")), any(unix, windows)))]
#[cfg(all(not(any(target_os = "solaris", target_os = "illumos", target_os = "freebsd")), any(unix, windows)))]
fn get_cpu_num() -> u32;
#[cfg(any(target_os = "macos", target_os = "windows"))]
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd"))]
fn get_cpu_speed() -> u64;

#[cfg(target_os = "windows")]
fn get_loadavg() -> LoadAvg;
#[cfg(any(target_os = "macos", target_os = "windows"))]
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd"))]
fn get_proc_total() -> u64;

#[cfg(any(target_os = "macos", target_os = "windows"))]
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd"))]
fn get_mem_info() -> MemInfo;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd"))]
fn get_disk_info() -> DiskInfo;
}

Expand Down Expand Up @@ -216,7 +216,11 @@ pub fn os_type() -> Result<String, Error> {
{
Ok("illumos".to_string())
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "solaris", target_os = "illumos")))]
#[cfg(target_os = "freebsd")]
{
Ok("freebsd".to_string())
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "solaris", target_os = "illumos", target_os = "freebsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand All @@ -233,7 +237,7 @@ pub fn os_release() -> Result<String, Error> {
s.pop(); // pop '\n'
Ok(s)
}
#[cfg(any(target_os = "macos", target_os = "windows"))]
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd"))]
{
let typ = unsafe { ffi::CStr::from_ptr(get_os_release() as *const c_char).to_bytes() };
Ok(String::from_utf8_lossy(typ).into_owned())
Expand All @@ -254,7 +258,7 @@ pub fn os_release() -> Result<String, Error> {
Some(release) => Ok(release),
}
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "solaris", target_os = "illumos")))]
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "solaris", target_os = "illumos", target_os = "freebsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand Down Expand Up @@ -326,7 +330,7 @@ fn parse_line_for_linux_os_release(l: String) -> Option<(String, String)> {
///
/// Notice, it returns the logical cpu quantity.
pub fn cpu_num() -> Result<u32, Error> {
#[cfg(any(target_os = "solaris", target_os = "illumos"))]
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "freebsd"))]
{
let ret = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
if ret < 1 || ret > std::u32::MAX as i64 {
Expand All @@ -335,7 +339,7 @@ pub fn cpu_num() -> Result<u32, Error> {
Ok(ret as u32)
}
}
#[cfg(all(not(any(target_os = "solaris", target_os = "illumos")), any(unix, windows)))]
#[cfg(all(not(any(target_os = "solaris", target_os = "illumos", target_os="freebsd")), any(unix, windows)))]
{
unsafe { Ok(get_cpu_num()) }
}
Expand Down Expand Up @@ -371,11 +375,11 @@ pub fn cpu_speed() -> Result<u64, Error> {
.map(|speed| speed as u64)
.ok_or(Error::Unknown)
}
#[cfg(any(target_os = "macos", target_os = "windows"))]
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd"))]
{
unsafe { Ok(get_cpu_speed()) }
}
#[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "linux", target_os = "macos", target_os = "windows")))]
#[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand All @@ -399,7 +403,7 @@ pub fn loadavg() -> Result<LoadAvg, Error> {
fifteen: loads[2],
})
}
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "macos"))]
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "freebsd"))]
{
let mut l: [c_double; 3] = [0f64; 3];
if unsafe { libc::getloadavg(l.as_mut_ptr(), l.len() as c_int) } < 3 {
Expand All @@ -416,7 +420,7 @@ pub fn loadavg() -> Result<LoadAvg, Error> {
{
Ok(unsafe { get_loadavg() })
}
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows")))]
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows", target_os = "freebsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand All @@ -438,11 +442,11 @@ pub fn proc_total() -> Result<u64, Error> {
.and_then(|val| val.parse::<u64>().ok())
.ok_or(Error::Unknown)
}
#[cfg(any(target_os = "macos", target_os = "windows"))]
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd"))]
{
Ok(unsafe { get_proc_total() })
}
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows")))]
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows", target_os = "freebsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand Down Expand Up @@ -512,11 +516,11 @@ pub fn mem_info() -> Result<MemInfo, Error> {
swap_free: 0,
});
}
#[cfg(any(target_os = "macos", target_os = "windows"))]
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd"))]
{
Ok(unsafe { get_mem_info() })
}
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows")))]
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows", target_os = "freebsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand All @@ -526,11 +530,11 @@ pub fn mem_info() -> Result<MemInfo, Error> {
///
/// Notice, it just calculate current disk on Windows.
pub fn disk_info() -> Result<DiskInfo, Error> {
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd"))]
{
Ok(unsafe { get_disk_info() })
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand Down Expand Up @@ -579,9 +583,9 @@ pub fn boottime() -> Result<timeval, Error> {
bt.tv_sec = secs[0] as libc::time_t;
bt.tv_usec = secs[1] as libc::suseconds_t;
}
#[cfg(target_os = "macos")]
#[cfg(any(target_os = "macos", target_os="freebsd"))]
{
let mut mib = [MAC_CTL_KERN, MAC_KERN_BOOTTIME];
let mut mib = [OS_CTL_KERN, OS_KERN_BOOTTIME];
let mut size: libc::size_t = size_of_val(&bt) as libc::size_t;
unsafe {
sysctl(&mut mib[0], 2,
Expand Down