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

Adds support for NetBSD platform. #91

Merged
merged 3 commits into from
Apr 9, 2021
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

Get system information in Rust.

For now it supports Linux, Mac OS X, illumos, Solaris, FreeBSD, OpenBSD, and Windows.
For now it supports Linux, Mac OS X, illumos, Solaris, FreeBSD, OpenBSD, NetBSD and Windows.
And now it can get information of kernel/cpu/memory/disk/load/hostname and so on.

[Documentation](https://docs.rs/sys-info)
Expand Down
4 changes: 4 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ fn main() {
println!("cargo:rustc-flags=-l pthread");
builder.file("c/openbsd.c")
},
"netbsd" => {
println!("cargo:rustc-flags=-l pthread");
builder.file("c/netbsd.c")
},
_ => panic!("unsupported system: {}", target_os)
};
builder.compile("info");
Expand Down
140 changes: 140 additions & 0 deletions c/netbsd.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/resource.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <sys/swap.h>
#include <sys/sysctl.h>
#include <sys/utsname.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <kvm.h>

#include <uvm/uvm_extern.h>

#include "info.h"

#define ONE_K 1024L
#define ONE_DECIMAL_K 1000L

#ifndef PAGE_SIZE
#define PAGE_SIZE ( sysconf(_SC_PAGESIZE) )
#endif
#define PAGE_SIZE_KB ( PAGE_SIZE / ONE_K )

static const char *os_release;

static pthread_once_t once_init_netbsd;
static void init_netbsd(void) {
struct utsname un;

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

const char *get_os_release(void) {
pthread_once(&once_init_netbsd, init_netbsd);
return (os_release);
}

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

#if defined(__i386__) || defined(__amd64__)
len = sizeof(tsc_freq);
error = sysctlbyname("machdep.tsc_freq", &tsc_freq, &len, NULL, 0);
if (error == -1)
return (0);
#else
tsc_freq = ONE_DECIMAL_K * ONE_DECIMAL_K * ONE_DECIMAL_K;
#endif
return (tsc_freq / ONE_DECIMAL_K / ONE_DECIMAL_K);
}

unsigned long get_proc_total(void) {
char errbuf[_POSIX2_LINE_MAX];
int count;
kvm_t *kd;
struct kinfo_proc *kp;

if ((kd = kvm_openfiles(NULL, NULL, NULL, KVM_NO_FILES, errbuf)) == NULL)
return (0);

if ((kp = kvm_getprocs(kd, KERN_PROC_ALL, 0, &count)) == NULL) {
(void) kvm_close(kd);
return(0);
}

kvm_close(kd);
free(kp);
return (unsigned long) (count);
}

int32_t get_mem_info_bsd(struct MemInfo *mi) {
static int uvmexp_mib[] = {CTL_VM, VM_UVMEXP2};
struct uvmexp_sysctl uvmexp;
size_t size_uvmexp = sizeof(uvmexp);
int error;

error = sysctl(uvmexp_mib, 2, &uvmexp, &size_uvmexp, NULL, 0);
if (error == -1)
goto fail;

// These calculations have been taken from sys/miscfs/procfs
// They need review for testing the correctness
mi->total = (uint64_t)uvmexp.npages * PAGE_SIZE_KB / ONE_K;
mi->avail = 0;
mi->free = (uint64_t)uvmexp.free * PAGE_SIZE_KB / ONE_K;
mi->cached = (uvmexp.anonpages + uvmexp.filepages + uvmexp.execpages) * PAGE_SIZE_KB / ONE_K;
mi->buffers = uvmexp.filepages * PAGE_SIZE_KB / ONE_K;
mi->swap_total = uvmexp.swpages * PAGE_SIZE_KB / ONE_K;
mi->swap_free = (uvmexp.swpages - uvmexp.swpginuse) * PAGE_SIZE_KB / ONE_K;
return (0);

fail:
return (-1);
}

int32_t get_disk_info_bsd(DiskInfo *di) {
struct statvfs *svfs, *svf;
int i, nmounts;
uint64_t dtotal, dfree;
int32_t res = 0;

dtotal = 0;
dfree = 0;
svfs = NULL;
res = -1;

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

for (i = 0; i < nmounts; i++) {
svf = &svfs[i];
if ((svf->f_flag & MNT_LOCAL) != MNT_LOCAL)
continue;
dtotal += svf->f_blocks * svf->f_bsize;
dfree += svf->f_bfree * svf->f_bsize;
}

di->total = dtotal / 1000;
di->free = dfree / 1000;
res = 0;

fail:
free(svfs);
return (res);
}
60 changes: 32 additions & 28 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", target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "windows", target_os = "macos", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
use std::os::raw::c_char;
#[cfg(not(any(target_os = "windows", target_os = "linux")))]
use std::os::raw::{c_int, c_double};

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

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

/// System load average value.
Expand Down Expand Up @@ -353,27 +353,27 @@ 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", target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
fn get_os_release() -> *const i8;

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

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

#[cfg(any(target_os = "macos", target_os = "windows"))]
fn get_mem_info() -> MemInfo;
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
fn get_mem_info_bsd(mi: &mut MemInfo) ->i32;

#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))]
fn get_disk_info() -> DiskInfo;
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
fn get_disk_info_bsd(di: &mut DiskInfo) -> i32;
}

Expand Down Expand Up @@ -410,7 +410,11 @@ pub fn os_type() -> Result<String, Error> {
{
Ok("openbsd".to_string())
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "solaris", target_os = "illumos", target_os = "freebsd", target_os = "openbsd")))]
#[cfg(target_os = "netbsd")]
{
Ok("netbsd".to_string())
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "solaris", target_os = "illumos", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand All @@ -427,7 +431,7 @@ pub fn os_release() -> Result<String, Error> {
s.pop(); // pop '\n'
Ok(s)
}
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
{
unsafe {
let rp = get_os_release() as *const c_char;
Expand Down Expand Up @@ -455,7 +459,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", target_os = "freebsd", target_os = "openbsd")))]
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "solaris", target_os = "illumos", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand Down Expand Up @@ -532,7 +536,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", target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
{
let ret = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
if ret < 1 || ret > std::u32::MAX as i64 {
Expand All @@ -541,7 +545,7 @@ pub fn cpu_num() -> Result<u32, Error> {
Ok(ret as u32)
}
}
#[cfg(all(not(any(target_os = "solaris", target_os = "illumos", target_os="freebsd", target_os = "openbsd")), any(unix, windows)))]
#[cfg(all(not(any(target_os = "solaris", target_os = "illumos", target_os="freebsd", target_os = "openbsd", target_os = "netbsd")), any(unix, windows)))]
{
unsafe { Ok(get_cpu_num()) }
}
Expand Down Expand Up @@ -581,15 +585,15 @@ pub fn cpu_speed() -> Result<u64, Error> {
{
unsafe { Ok(get_cpu_speed()) }
}
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
{
let res: u64 = unsafe { get_cpu_speed() };
match res {
0 => Err(Error::IO(io::Error::last_os_error())),
_ => Ok(res),
}
}
#[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd")))]
#[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand All @@ -613,7 +617,7 @@ pub fn loadavg() -> Result<LoadAvg, Error> {
fifteen: loads[2],
})
}
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
{
let mut l: [c_double; 3] = [0f64; 3];
if unsafe { libc::getloadavg(l.as_mut_ptr(), l.len() as c_int) } < 3 {
Expand All @@ -630,7 +634,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", target_os = "freebsd", target_os = "openbsd")))]
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand All @@ -656,15 +660,15 @@ pub fn proc_total() -> Result<u64, Error> {
{
Ok(unsafe { get_proc_total() })
}
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
{
let res: u64 = unsafe { get_proc_total() };
match res {
0 => Err(Error::IO(io::Error::last_os_error())),
_ => Ok(res),
}
}
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd")))]
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand Down Expand Up @@ -738,7 +742,7 @@ pub fn mem_info() -> Result<MemInfo, Error> {
{
Ok(unsafe { get_mem_info() })
}
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
{
let mut mi:MemInfo = MemInfo{total: 0, free: 0, avail: 0, buffers: 0,
cached: 0, swap_total: 0, swap_free: 0};
Expand All @@ -749,7 +753,7 @@ pub fn mem_info() -> Result<MemInfo, Error> {
_ => Err(Error::Unknown),
}
}
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd")))]
#[cfg(not(any(target_os = "linux", target_os = "solaris", target_os = "illumos", target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand All @@ -763,7 +767,7 @@ pub fn disk_info() -> Result<DiskInfo, Error> {
{
Ok(unsafe { get_disk_info() })
}
#[cfg(any(target_os = "freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "freebsd", target_os = "openbsd", target_os = "netbsd"))]
{
let mut di:DiskInfo = DiskInfo{total: 0, free: 0};
let res: i32 = unsafe { get_disk_info_bsd(&mut di) };
Expand All @@ -773,7 +777,7 @@ pub fn disk_info() -> Result<DiskInfo, Error> {
_ => Err(Error::Unknown),
}
}
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd")))]
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "freebsd", target_os = "openbsd", target_os = "netbsd")))]
{
Err(Error::UnsupportedSystem)
}
Expand Down Expand Up @@ -823,7 +827,7 @@ pub fn boottime() -> Result<timeval, Error> {
bt.tv_usec = secs[1] as libc::suseconds_t;
Ok(bt)
}
#[cfg(any(target_os = "macos", target_os="freebsd", target_os = "openbsd"))]
#[cfg(any(target_os = "macos", target_os="freebsd", target_os = "openbsd", target_os = "netbsd"))]
{
let mut mib = [OS_CTL_KERN, OS_KERN_BOOTTIME];
let mut size: libc::size_t = size_of_val(&bt) as libc::size_t;
Expand Down