1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
//---------------------------------------------------------------------------------------------------- Use
use crate::up::{
Uptime,
UptimeFull,
Htop,
};
use crate::time::TimeUnit;
//---------------------------------------------------------------------------------------------------- SysUptime Trait
/// System uptime
///
/// This trait represents structures that are viable containers for holding and
/// displaying system uptime, notably, everything in the `readable::time` module.
///
/// `readable::run` types do not implement this trait as
/// they have a relatively low upper limit of `99` hours.
///
/// This trait is sealed and can only be implemented internally on `readable` types.
pub trait SysUptime: private::Sealed {
/// This function creates a `Self` from the live system uptime and can be used on:
/// - Windows
/// - macOS
/// - BSDs
/// - Linux
///
/// ## Example
/// ```rust
/// # use readable::*;
/// // Introduce trait into scope.
/// use readable::SysUptime;
///
/// // Capture the _current_ system uptime,
/// // and format it into a `Uptime`.
/// std::thread::sleep(std::time::Duration::from_secs(1));
/// let mut uptime: Uptime = Uptime::sys_uptime();
/// # // Get around CI.
/// # let uptime = 1;
/// assert!(uptime >= 1);
/// ```
fn sys_uptime() -> Self;
}
//---------------------------------------------------------------------------------------------------- SysUptime Function
#[inline]
/// Get the current system uptime in seconds
///
/// This function can be used on:
/// - Windows
/// - macOS
/// - BSDs
/// - Linux
///
/// This will return `0` if the underlying system call fails.
pub fn uptime() -> u32 {
// SAFETY: we're calling C.
#[cfg(target_os = "windows")]
{
let milliseconds = unsafe { windows::Win32::System::SystemInformation::GetTickCount64() };
return (milliseconds as f64 / 1000.0) as u32;
}
#[cfg(all(target_os = "unix", not(target_os = "linux")))]
{
use std::time::{Duration,SystemTime};
let mut request = [libc::CTL_KERN, libc::KERN_BOOTTIME];
let mut timeval = libc::timeval {
tv_sec: 0,
tv_nsec: 0,
};
let mut size: libc::size_t = std::mem::size_of_val(&timeval);
let err = unsafe { libc::sysctl(
&mut request[0],
2,
&mut timeval as _,
&mut size,
std::ptr::null_mut(),
0,
)};
if err == 0 {
if let Ok(mut sys) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
return sys - Duration::from_secs(timeval.tv_sec as u64);
}
}
}
#[cfg(target_os = "linux")]
{
let mut timespec = libc::timespec {
tv_sec: 0,
tv_nsec: 0,
};
let ptr = std::ptr::addr_of_mut!(timespec);
// Get time, ignore return error.
unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, ptr) };
// Uptime is set if no error, else
// our default `0` is returned.
return timespec.tv_sec as u32;
}
0
}
//---------------------------------------------------------------------------------------------------- SysUptime Impl
mod private {
use super::*;
pub trait Sealed {}
impl Sealed for Uptime {}
impl Sealed for UptimeFull {}
impl Sealed for Htop {}
impl Sealed for TimeUnit {}
}
macro_rules! impl_uptime {
($($time:ty),*) => {
$(
impl SysUptime for $time {
#[inline]
fn sys_uptime() -> Self {
Self::from(uptime())
}
}
)*
};
}
impl_uptime!(Uptime, UptimeFull, Htop, TimeUnit);