// Take a look at the license at the top of the repository in the LICENSE file. use crate::{CpuExt, NetworkExt, NetworksExt, Pid, Process, ProcessExt, System, SystemExt}; use libc::{self, c_char, c_float, c_uint, c_void, pid_t, size_t}; use std::borrow::BorrowMut; use std::ffi::CString; /// Equivalent of [`System`][crate::System] struct. pub type CSystem = *mut c_void; /// Equivalent of [`Process`][crate::Process] struct. pub type CProcess = *const c_void; /// C string returned from `CString::into_raw`. pub type RString = *const c_char; /// Callback used by [`processes`][crate::System#method.processes]. pub type ProcessLoop = extern "C" fn(pid: pid_t, process: CProcess, data: *mut c_void) -> bool; /// Equivalent of [`System::new()`][crate::System#method.new]. #[no_mangle] pub extern "C" fn sysinfo_init() -> CSystem { let system = Box::new(System::new()); Box::into_raw(system) as CSystem } /// Equivalent of `System::drop()`. Important in C to cleanup memory. #[no_mangle] pub extern "C" fn sysinfo_destroy(system: CSystem) { assert!(!system.is_null()); unsafe { drop(Box::from_raw(system as *mut System)); } } /// Equivalent of [`System::refresh_system()`][crate::System#method.refresh_system]. #[no_mangle] pub extern "C" fn sysinfo_refresh_system(system: CSystem) { assert!(!system.is_null()); unsafe { let mut system: Box = Box::from_raw(system as *mut System); { let system: &mut System = system.borrow_mut(); system.refresh_system(); } Box::into_raw(system); } } /// Equivalent of [`System::refresh_memory()`][crate::System#method.refresh_memory]. #[no_mangle] pub extern "C" fn sysinfo_refresh_memory(system: CSystem) { assert!(!system.is_null()); unsafe { let mut system: Box = Box::from_raw(system as *mut System); { let system: &mut System = system.borrow_mut(); system.refresh_memory(); } Box::into_raw(system); } } /// Equivalent of [`System::refresh_cpu()`][crate::System#method.refresh_cpu]. #[no_mangle] pub extern "C" fn sysinfo_refresh_cpu(system: CSystem) { assert!(!system.is_null()); unsafe { let mut system: Box = Box::from_raw(system as *mut System); { let system: &mut System = system.borrow_mut(); system.refresh_cpu(); } Box::into_raw(system); } } /// Equivalent of [`System::refresh_components()`][crate::System#method.refresh_temperatures]. #[no_mangle] pub extern "C" fn sysinfo_refresh_components(system: CSystem) { assert!(!system.is_null()); unsafe { let mut system: Box = Box::from_raw(system as *mut System); { let system: &mut System = system.borrow_mut(); system.refresh_components(); } Box::into_raw(system); } } /// Equivalent of [`System::refresh_all()`][crate::System#method.refresh_all]. #[no_mangle] pub extern "C" fn sysinfo_refresh_all(system: CSystem) { assert!(!system.is_null()); unsafe { let mut system: Box = Box::from_raw(system as *mut System); { let system: &mut System = system.borrow_mut(); system.refresh_all(); } Box::into_raw(system); } } /// Equivalent of [`System::refresh_processes()`][crate::System#method.refresh_processes]. #[no_mangle] pub extern "C" fn sysinfo_refresh_processes(system: CSystem) { assert!(!system.is_null()); unsafe { let mut system: Box = Box::from_raw(system as *mut System); { let system: &mut System = system.borrow_mut(); system.refresh_processes(); } Box::into_raw(system); } } /// Equivalent of [`System::refresh_process()`][crate::System#method.refresh_process]. #[cfg(target_os = "linux")] #[no_mangle] pub extern "C" fn sysinfo_refresh_process(system: CSystem, pid: pid_t) { assert!(!system.is_null()); unsafe { let mut system: Box = Box::from_raw(system as *mut System); { let system: &mut System = system.borrow_mut(); system.refresh_process(Pid(pid)); } Box::into_raw(system); } } /// Equivalent of [`System::refresh_disks()`][crate::System#method.refresh_disks]. #[no_mangle] pub extern "C" fn sysinfo_refresh_disks(system: CSystem) { assert!(!system.is_null()); unsafe { let mut system: Box = Box::from_raw(system as *mut System); { let system: &mut System = system.borrow_mut(); system.refresh_disks(); } Box::into_raw(system); } } /// Equivalent of [`System::refresh_disks_list()`][crate::System#method.refresh_disks_list]. #[no_mangle] pub extern "C" fn sysinfo_refresh_disks_list(system: CSystem) { assert!(!system.is_null()); unsafe { let mut system: Box = Box::from_raw(system as *mut System); { let system: &mut System = system.borrow_mut(); system.refresh_disks_list(); } Box::into_raw(system); } } /// Equivalent of [`System::total_memory()`][crate::System#method.total_memory]. #[no_mangle] pub extern "C" fn sysinfo_total_memory(system: CSystem) -> size_t { assert!(!system.is_null()); unsafe { let system: Box = Box::from_raw(system as *mut System); let ret = system.total_memory() as size_t; Box::into_raw(system); ret } } /// Equivalent of [`System::free_memory()`][crate::System#method.free_memory]. #[no_mangle] pub extern "C" fn sysinfo_free_memory(system: CSystem) -> size_t { assert!(!system.is_null()); unsafe { let system: Box = Box::from_raw(system as *mut System); let ret = system.free_memory() as size_t; Box::into_raw(system); ret } } /// Equivalent of [`System::used_memory()`][crate::System#method.used_memory]. #[no_mangle] pub extern "C" fn sysinfo_used_memory(system: CSystem) -> size_t { assert!(!system.is_null()); let system: Box = unsafe { Box::from_raw(system as *mut System) }; let ret = system.used_memory() as size_t; Box::into_raw(system); ret } /// Equivalent of [`System::total_swap()`][crate::System#method.total_swap]. #[no_mangle] pub extern "C" fn sysinfo_total_swap(system: CSystem) -> size_t { assert!(!system.is_null()); unsafe { let system: Box = Box::from_raw(system as *mut System); let ret = system.total_swap() as size_t; Box::into_raw(system); ret } } /// Equivalent of [`System::free_swap()`][crate::System#method.free_swap]. #[no_mangle] pub extern "C" fn sysinfo_free_swap(system: CSystem) -> size_t { assert!(!system.is_null()); unsafe { let system: Box = Box::from_raw(system as *mut System); let ret = system.free_swap() as size_t; Box::into_raw(system); ret } } /// Equivalent of [`System::used_swap()`][crate::System#method.used_swap]. #[no_mangle] pub extern "C" fn sysinfo_used_swap(system: CSystem) -> size_t { assert!(!system.is_null()); unsafe { let system: Box = Box::from_raw(system as *mut System); let ret = system.used_swap() as size_t; Box::into_raw(system); ret } } /// Equivalent of /// `system::networks().iter().fold(0, |acc, (_, data)| acc + data.received() as size_t)`. #[no_mangle] pub extern "C" fn sysinfo_networks_received(system: CSystem) -> size_t { assert!(!system.is_null()); unsafe { let system: Box = Box::from_raw(system as *mut System); let ret = system.networks().iter().fold(0, |acc: size_t, (_, data)| { acc.saturating_add(data.received() as size_t) }); Box::into_raw(system); ret } } /// Equivalent of /// `system::networks().iter().fold(0, |acc, (_, data)| acc + data.transmitted() as size_t)`. #[no_mangle] pub extern "C" fn sysinfo_networks_transmitted(system: CSystem) -> size_t { assert!(!system.is_null()); unsafe { let system: Box = Box::from_raw(system as *mut System); let ret = system.networks().iter().fold(0, |acc: size_t, (_, data)| { acc.saturating_add(data.transmitted() as size_t) }); Box::into_raw(system); ret } } /// Equivalent of [`System::cpus_usage()`][crate::System#method.cpus_usage]. /// /// * `length` will contain the number of CPU usage added into `procs`. /// * `procs` will be allocated if it's null and will contain of CPU usage. #[no_mangle] pub extern "C" fn sysinfo_cpus_usage( system: CSystem, length: *mut c_uint, procs: *mut *mut c_float, ) { assert!(!system.is_null()); if procs.is_null() || length.is_null() { return; } unsafe { let system: Box = Box::from_raw(system as *mut System); { let cpus = system.cpus(); if (*procs).is_null() { (*procs) = libc::malloc(::std::mem::size_of::() * cpus.len()) as *mut c_float; } for (pos, cpu) in cpus.iter().skip(1).enumerate() { (*(*procs).offset(pos as isize)) = cpu.cpu_usage(); } *length = cpus.len() as c_uint - 1; } Box::into_raw(system); } } /// Equivalent of [`System::processes()`][crate::System#method.processes]. Returns an /// array ended by a null pointer. Must be freed. /// /// # ⚠️ WARNING ⚠️ /// /// While having this method returned processes, you should *never* call any refresh method! #[no_mangle] pub extern "C" fn sysinfo_processes( system: CSystem, fn_pointer: Option, data: *mut c_void, ) -> size_t { assert!(!system.is_null()); if let Some(fn_pointer) = fn_pointer { unsafe { let system: Box = Box::from_raw(system as *mut System); let len = { let entries = system.processes(); for (pid, process) in entries { if !fn_pointer(pid.0, process as *const Process as CProcess, data) { break; } } entries.len() as size_t }; Box::into_raw(system); len } } else { 0 } } /// Equivalent of [`System::process()`][crate::System#method.process]. /// /// # ⚠️ WARNING ⚠️ /// /// While having this method returned process, you should *never* call any /// refresh method! #[no_mangle] pub extern "C" fn sysinfo_process_by_pid(system: CSystem, pid: pid_t) -> CProcess { assert!(!system.is_null()); unsafe { let system: Box = Box::from_raw(system as *mut System); let ret = if let Some(process) = system.process(Pid(pid)) { process as *const Process as CProcess } else { std::ptr::null() }; Box::into_raw(system); ret } } /// Equivalent of iterating over [`Process::tasks()`][crate::Process#method.tasks]. /// /// # ⚠️ WARNING ⚠️ /// /// While having this method processes, you should *never* call any refresh method! #[cfg(target_os = "linux")] #[no_mangle] pub extern "C" fn sysinfo_process_tasks( process: CProcess, fn_pointer: Option, data: *mut c_void, ) -> size_t { assert!(!process.is_null()); if let Some(fn_pointer) = fn_pointer { unsafe { let process = process as *const Process; for (pid, process) in (*process).tasks.iter() { if !fn_pointer(pid.0, process as *const Process as CProcess, data) { break; } } (*process).tasks.len() as size_t } } else { 0 } } /// Equivalent of [`Process::pid()`][crate::Process#method.pid]. #[no_mangle] pub extern "C" fn sysinfo_process_pid(process: CProcess) -> pid_t { assert!(!process.is_null()); let process = process as *const Process; unsafe { (*process).pid().0 } } /// Equivalent of [`Process::parent()`][crate::Process#method.parent]. /// /// In case there is no known parent, it returns `0`. #[no_mangle] pub extern "C" fn sysinfo_process_parent_pid(process: CProcess) -> pid_t { assert!(!process.is_null()); let process = process as *const Process; unsafe { (*process).parent().unwrap_or(Pid(0)).0 } } /// Equivalent of [`Process::cpu_usage()`][crate::Process#method.cpu_usage]. #[no_mangle] pub extern "C" fn sysinfo_process_cpu_usage(process: CProcess) -> c_float { assert!(!process.is_null()); let process = process as *const Process; unsafe { (*process).cpu_usage() } } /// Equivalent of [`Process::memory()`][crate::Process#method.memory]. #[no_mangle] pub extern "C" fn sysinfo_process_memory(process: CProcess) -> size_t { assert!(!process.is_null()); let process = process as *const Process; unsafe { (*process).memory() as usize } } /// Equivalent of [`Process::virtual_memory()`][crate::Process#method.virtual_memory]. #[no_mangle] pub extern "C" fn sysinfo_process_virtual_memory(process: CProcess) -> size_t { assert!(!process.is_null()); let process = process as *const Process; unsafe { (*process).virtual_memory() as usize } } /// Equivalent of [`Process::exe()`][crate::Process#method.exe]. #[no_mangle] pub extern "C" fn sysinfo_process_executable_path(process: CProcess) -> RString { assert!(!process.is_null()); let process = process as *const Process; unsafe { if let Some(p) = (*process).exe().to_str() { if let Ok(c) = CString::new(p) { return c.into_raw() as _; } } std::ptr::null() } } /// Equivalent of [`Process::root()`][crate::Process#method.root]. #[no_mangle] pub extern "C" fn sysinfo_process_root_directory(process: CProcess) -> RString { assert!(!process.is_null()); let process = process as *const Process; unsafe { if let Some(p) = (*process).root().to_str() { if let Ok(c) = CString::new(p) { return c.into_raw() as _; } } std::ptr::null() } } /// Equivalent of [`Process::cwd()`][crate::Process#method.cwd]. #[no_mangle] pub extern "C" fn sysinfo_process_current_directory(process: CProcess) -> RString { assert!(!process.is_null()); let process = process as *const Process; unsafe { if let Some(p) = (*process).cwd().to_str() { if let Ok(c) = CString::new(p) { return c.into_raw() as _; } } std::ptr::null() } } /// Frees a C string created with `CString::into_raw()`. #[no_mangle] pub extern "C" fn sysinfo_rstring_free(s: RString) { if !s.is_null() { unsafe { let _ = CString::from_raw(s as usize as *mut _); } } }