#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(dead_code)]
use std::mem::size_of;
use std::os::raw::{c_char, c_int, c_void};
use std::ptr;
use crate::ported::batterymeter::ACPresence;
use crate::ported::diskiometer::DiskIOData;
use crate::ported::machine::Machine;
use crate::ported::meter::Meter;
use crate::ported::networkiometer::NetworkIOData;
use crate::ported::openbsd::openbsdmachine::{
kvm_close, kvm_getenvv, kvm_getprocs, kvm_openfiles, OpenBSDMachine, KVM_NO_FILES,
_POSIX2_LINE_MAX,
};
const VM_LOADAVG: c_int = 2;
const THREAD_PID_OFFSET: libc::pid_t = 100000;
#[repr(C)]
struct loadavg {
ldavg: [u32; 3],
fscale: libc::c_long,
}
const CPU_METER_NICE: usize = 0;
const CPU_METER_NORMAL: usize = 1;
const CPU_METER_KERNEL: usize = 2;
const CPU_METER_IRQ: usize = 3;
const CPU_METER_SOFTIRQ: usize = 4;
const CPU_METER_STEAL: usize = 5;
const CPU_METER_GUEST: usize = 6;
const CPU_METER_IOWAIT: usize = 7;
const CPU_METER_FREQUENCY: usize = 8;
const CPU_METER_TEMPERATURE: usize = 9;
const MEMORY_CLASS_WIRED: usize = 0;
const MEMORY_CLASS_CACHE: usize = 1;
const MEMORY_CLASS_ACTIVE: usize = 2;
const MEMORY_CLASS_PAGING: usize = 3;
const MEMORY_CLASS_INACTIVE: usize = 4;
const SWAP_METER_USED: usize = 0;
const HW_SENSORS: c_int = 11;
const SENSOR_WATTHOUR: c_int = 7;
const SENSOR_INDICATOR: c_int = 9;
const SENSOR_MAX_TYPES: usize = 23;
#[repr(C)]
#[derive(Clone, Copy)]
struct sensor {
desc: [c_char; 32],
tv: libc::timeval,
value: i64,
type_: c_int,
status: c_int,
numt: c_int,
flags: c_int,
}
#[repr(C)]
#[derive(Clone, Copy)]
struct sensordev {
num: c_int,
xname: [c_char; 16],
maxnumt: [c_int; SENSOR_MAX_TYPES],
sensors_count: c_int,
}
pub fn Platform_init() -> bool {
true
}
pub fn Platform_done() {
}
pub fn Platform_setBindings() {
}
pub fn Platform_getUptime() -> c_int {
let mut bootTime: libc::timeval = unsafe { std::mem::zeroed() };
let mib: [c_int; 2] = [libc::CTL_KERN, libc::KERN_BOOTTIME];
let mut size = size_of::<libc::timeval>();
let err = unsafe {
libc::sysctl(
mib.as_ptr(),
2,
&mut bootTime as *mut libc::timeval as *mut c_void,
&mut size,
ptr::null_mut(),
0,
)
};
if err != 0 {
return -1;
}
let mut currTime: libc::timeval = unsafe { std::mem::zeroed() };
unsafe { libc::gettimeofday(&mut currTime, ptr::null_mut()) };
(currTime.tv_sec - bootTime.tv_sec) as c_int
}
pub fn Platform_getLoadAverage(one: &mut f64, five: &mut f64, fifteen: &mut f64) {
let mut loadAverage: loadavg = unsafe { std::mem::zeroed() };
let mib: [c_int; 2] = [libc::CTL_VM, VM_LOADAVG];
let mut size = size_of::<loadavg>();
let err = unsafe {
libc::sysctl(
mib.as_ptr(),
2,
&mut loadAverage as *mut loadavg as *mut c_void,
&mut size,
ptr::null_mut(),
0,
)
};
if err != 0 {
*one = 0.0;
*five = 0.0;
*fifteen = 0.0;
return;
}
*one = loadAverage.ldavg[0] as f64 / loadAverage.fscale as f64;
*five = loadAverage.ldavg[1] as f64 / loadAverage.fscale as f64;
*fifteen = loadAverage.ldavg[2] as f64 / loadAverage.fscale as f64;
}
pub fn Platform_getMaxPid() -> libc::pid_t {
2 * THREAD_PID_OFFSET
}
pub fn Platform_setCPUValues(mtr: &mut Meter, cpu: u32) -> f64 {
let host = mtr.host;
let ohost = host as *const OpenBSDMachine;
let cpuData = unsafe { &(*ohost).cpuData[cpu as usize] };
if !cpuData.online {
mtr.curItems = 0;
return f64::NAN;
}
let total = if cpuData.totalPeriod == 0 {
1.0
} else {
cpuData.totalPeriod as f64
};
mtr.values[CPU_METER_NICE] = cpuData.nicePeriod as f64 / total * 100.0;
mtr.values[CPU_METER_NORMAL] = cpuData.userPeriod as f64 / total * 100.0;
let detailed = unsafe {
(*host)
.settings
.as_ref()
.is_some_and(|s| s.detailedCPUTime)
};
if detailed {
mtr.values[CPU_METER_KERNEL] = cpuData.sysPeriod as f64 / total * 100.0;
mtr.values[CPU_METER_IRQ] = cpuData.intrPeriod as f64 / total * 100.0;
mtr.values[CPU_METER_SOFTIRQ] = 0.0;
mtr.values[CPU_METER_STEAL] = 0.0;
mtr.values[CPU_METER_GUEST] = 0.0;
mtr.values[CPU_METER_IOWAIT] = 0.0;
mtr.values[CPU_METER_FREQUENCY] = f64::NAN;
mtr.curItems = 8;
} else {
mtr.values[CPU_METER_KERNEL] = cpuData.sysAllPeriod as f64 / total * 100.0;
mtr.values[CPU_METER_IRQ] = 0.0; mtr.curItems = 4;
}
let mut totalPercent = mtr.values[CPU_METER_NICE]
+ mtr.values[CPU_METER_NORMAL]
+ mtr.values[CPU_METER_KERNEL]
+ mtr.values[CPU_METER_IRQ];
totalPercent = totalPercent.clamp(0.0, 100.0);
mtr.values[CPU_METER_TEMPERATURE] = f64::NAN;
let cpuSpeed = unsafe { (*ohost).cpuSpeed };
mtr.values[CPU_METER_FREQUENCY] = if cpuSpeed != -1 {
cpuSpeed as f64
} else {
f64::NAN
};
totalPercent
}
pub fn Platform_setMemoryValues(mtr: &mut Meter) {
let host = mtr.host;
let ohost = host as *const OpenBSDMachine;
mtr.total = unsafe { (*host).totalMem } as f64;
let show_cached = unsafe {
(*host)
.settings
.as_ref()
.is_some_and(|s| s.showCachedMemory)
};
let o = unsafe { &*ohost };
if show_cached {
mtr.values[MEMORY_CLASS_WIRED] = o.wiredMem as f64;
mtr.values[MEMORY_CLASS_CACHE] = o.cacheMem as f64;
} else {
mtr.values[MEMORY_CLASS_WIRED] = (o.wiredMem + o.cacheMem) as f64;
mtr.values[MEMORY_CLASS_CACHE] = 0.0;
}
mtr.values[MEMORY_CLASS_ACTIVE] = o.activeMem as f64;
mtr.values[MEMORY_CLASS_PAGING] = o.pagingMem as f64;
mtr.values[MEMORY_CLASS_INACTIVE] = o.inactiveMem as f64;
}
pub fn Platform_setSwapValues(mtr: &mut Meter) {
let host: *const Machine = mtr.host;
mtr.total = unsafe { (*host).totalSwap } as f64;
mtr.values[SWAP_METER_USED] = unsafe { (*host).usedSwap } as f64;
}
pub fn Platform_getProcessEnv(pid: libc::pid_t) -> Option<String> {
let mut errbuf = [0 as c_char; _POSIX2_LINE_MAX];
let kt = unsafe {
kvm_openfiles(
ptr::null(),
ptr::null(),
ptr::null(),
KVM_NO_FILES,
errbuf.as_mut_ptr(),
)
};
if kt.is_null() {
return None;
}
let mut count: c_int = 0;
let kproc = unsafe {
kvm_getprocs(
kt,
libc::KERN_PROC_PID,
pid,
size_of::<libc::kinfo_proc>(),
&mut count,
)
};
if kproc.is_null() {
unsafe { kvm_close(kt) };
return None;
}
let ptrs = unsafe { kvm_getenvv(kt, kproc, 0) };
if ptrs.is_null() {
unsafe { kvm_close(kt) };
return None;
}
let mut env: Vec<u8> = Vec::new();
unsafe {
let mut i: isize = 0;
loop {
let p = *ptrs.offset(i);
if p.is_null() {
break;
}
env.extend_from_slice(std::ffi::CStr::from_ptr(p).to_bytes());
env.push(0);
i += 1;
}
kvm_close(kt);
}
env.push(0);
Some(String::from_utf8_lossy(&env).into_owned())
}
pub fn Platform_getProcessLocks() {
todo!("port of Platform.c:320 — FileLocks_ProcessData unmodeled (returns NULL)")
}
pub fn Platform_getFileDescriptors(used: &mut f64, max: &mut f64) {
let mib_kern_maxfile: [c_int; 2] = [libc::CTL_KERN, libc::KERN_MAXFILES];
let mut sysctl_maxfile: c_int = 0;
let mut size_maxfile = size_of::<c_int>();
if unsafe {
libc::sysctl(
mib_kern_maxfile.as_ptr(),
2,
&mut sysctl_maxfile as *mut c_int as *mut c_void,
&mut size_maxfile,
ptr::null_mut(),
0,
)
} < 0
{
*max = f64::NAN;
} else if size_maxfile != size_of::<c_int>() || sysctl_maxfile < 1 {
*max = f64::NAN;
} else {
*max = sysctl_maxfile as f64;
}
let mib_kern_nfiles: [c_int; 2] = [libc::CTL_KERN, libc::KERN_NFILES];
let mut sysctl_nfiles: c_int = 0;
let mut size_nfiles = size_of::<c_int>();
if unsafe {
libc::sysctl(
mib_kern_nfiles.as_ptr(),
2,
&mut sysctl_nfiles as *mut c_int as *mut c_void,
&mut size_nfiles,
ptr::null_mut(),
0,
)
} < 0
{
*used = f64::NAN;
} else if size_nfiles != size_of::<c_int>() || sysctl_nfiles < 0 {
*used = f64::NAN;
} else {
*used = sysctl_nfiles as f64;
}
}
pub fn Platform_getDiskIO(_data: &mut DiskIOData) -> bool {
false
}
pub fn Platform_getNetworkIO(_data: &mut NetworkIOData) -> bool {
false
}
fn findDevice(name: &str, mib: &mut [c_int; 5], snsrdev: &mut sensordev, sdlen: &mut usize) -> bool {
let mut devn: c_int = 0;
loop {
mib[2] = devn;
if unsafe {
libc::sysctl(
mib.as_ptr(),
3,
snsrdev as *mut sensordev as *mut c_void,
sdlen,
ptr::null_mut(),
0,
)
} == -1
{
match std::io::Error::last_os_error().raw_os_error() {
Some(e) if e == libc::ENXIO => {
devn += 1;
continue;
}
Some(e) if e == libc::ENOENT => return false,
_ => {}
}
}
let xname_bytes: &[u8] = unsafe {
core::slice::from_raw_parts(
snsrdev.xname.as_ptr() as *const u8,
snsrdev.xname.len(),
)
};
let n = xname_bytes
.iter()
.position(|&b| b == 0)
.unwrap_or(xname_bytes.len());
if name.as_bytes() == &xname_bytes[..n] {
return true;
}
devn += 1;
}
}
pub fn Platform_getBattery(percent: &mut f64, isOnAC: &mut ACPresence) {
let mut mib: [c_int; 5] = [libc::CTL_HW, HW_SENSORS, 0, 0, 0];
let mut s: sensor = unsafe { std::mem::zeroed() };
let mut slen = size_of::<sensor>();
let mut snsrdev: sensordev = unsafe { std::mem::zeroed() };
let mut sdlen = size_of::<sensordev>();
let found = findDevice("acpibat0", &mut mib, &mut snsrdev, &mut sdlen);
*percent = f64::NAN;
if found {
mib[3] = SENSOR_WATTHOUR;
mib[4] = 0;
let mut last_full_capacity = 0.0f64;
if unsafe {
libc::sysctl(
mib.as_ptr(),
5,
&mut s as *mut sensor as *mut c_void,
&mut slen,
ptr::null_mut(),
0,
)
} != -1
{
last_full_capacity = s.value as f64;
}
if last_full_capacity > 0.0 {
mib[3] = SENSOR_WATTHOUR;
mib[4] = 3;
if unsafe {
libc::sysctl(
mib.as_ptr(),
5,
&mut s as *mut sensor as *mut c_void,
&mut slen,
ptr::null_mut(),
0,
)
} != -1
{
let charge = s.value as f64;
*percent = 100.0 * (charge / last_full_capacity);
if charge >= last_full_capacity {
*percent = 100.0;
}
}
}
}
let found = findDevice("acpiac0", &mut mib, &mut snsrdev, &mut sdlen);
*isOnAC = ACPresence::AC_ERROR;
if found {
mib[3] = SENSOR_INDICATOR;
mib[4] = 0;
if unsafe {
libc::sysctl(
mib.as_ptr(),
5,
&mut s as *mut sensor as *mut c_void,
&mut slen,
ptr::null_mut(),
0,
)
} != -1
{
*isOnAC = if s.value != 0 {
ACPresence::AC_PRESENT
} else {
ACPresence::AC_ABSENT
};
}
}
}