diff options
| -rw-r--r-- | talpid-dbus/src/lib.rs | 1 | ||||
| -rw-r--r-- | talpid-dbus/src/systemd.rs | 67 |
2 files changed, 68 insertions, 0 deletions
diff --git a/talpid-dbus/src/lib.rs b/talpid-dbus/src/lib.rs index c4b9bb7e12..f85581864a 100644 --- a/talpid-dbus/src/lib.rs +++ b/talpid-dbus/src/lib.rs @@ -4,6 +4,7 @@ pub use dbus; use dbus::blocking::SyncConnection; use std::sync::{Arc, Mutex}; pub mod network_manager; +pub mod systemd; pub mod systemd_resolved; lazy_static::lazy_static! { diff --git a/talpid-dbus/src/systemd.rs b/talpid-dbus/src/systemd.rs new file mode 100644 index 0000000000..521f2a1b8e --- /dev/null +++ b/talpid-dbus/src/systemd.rs @@ -0,0 +1,67 @@ +use dbus::blocking::{stdintf::org_freedesktop_dbus::Properties, Proxy, SyncConnection}; +use std::{sync::Arc, time::Duration}; + +type Result<T> = std::result::Result<T, Error>; + +#[derive(err_derive::Error, Debug)] +#[error(no_from)] +pub enum Error { + #[error(display = "Failed to create a DBus connection")] + ConnectError(#[error(source)] dbus::Error), + + #[error(display = "Failed to read SystemState property")] + ReadSystemStateError(#[error(source)] dbus::Error), +} + +const SYSTEMD_BUS: &str = "org.freedesktop.systemd1"; +const SYSTEMD_PATH: &str = "/org/freedesktop/systemd1"; +const MANAGER_INTERFACE: &str = "org.freedesktop.systemd1.Manager"; +const SYSTEM_STATE: &str = "SystemState"; +const SYSTEM_STATE_STARTING: &str = "starting"; +const SYSTEM_STATE_INITIALIZING: &str = "initializing"; +const SYSTEM_STATE_RUNNING: &str = "running"; +const SYSTEM_STATE_DEGRADED: &str = "degraded"; + +const RPC_TIMEOUT: Duration = Duration::from_secs(1); + +/// Returns true if the host is not shutting down or entering maintenance mode or some other weird +/// state. +pub fn is_host_running() -> Result<bool> { + Systemd::new()?.system_is_running() +} + +struct Systemd { + pub dbus_connection: Arc<SyncConnection>, +} + +impl Systemd { + fn new() -> Result<Self> { + Ok(Self { + dbus_connection: crate::get_connection().map_err(Error::ConnectError)?, + }) + } + + fn system_is_running(&self) -> Result<bool> { + self.as_manager_object() + .get(MANAGER_INTERFACE, SYSTEM_STATE) + .map(|state: String| { + ![ + SYSTEM_STATE_STARTING, + SYSTEM_STATE_INITIALIZING, + SYSTEM_STATE_RUNNING, + SYSTEM_STATE_DEGRADED, + ] + .contains(&state.as_str()) + }) + .map_err(Error::ReadSystemStateError) + } + + fn as_manager_object(&self) -> Proxy<'_, &SyncConnection> { + Proxy::new( + SYSTEMD_BUS, + SYSTEMD_PATH, + RPC_TIMEOUT, + &self.dbus_connection, + ) + } +} |
