diff --git a/init.d/00_driver-manager.service b/init.d/00_driver-manager.service index 990c999000..fae8661059 100644 --- a/init.d/00_driver-manager.service +++ b/init.d/00_driver-manager.service @@ -23,4 +23,4 @@ args = ["--rootfs"] type = "oneshot_async" # Operator must explicitly enable this service: # touch /etc/driver-manager.d/disabled # force fallback to pcid-spawner -ConditionPathExists = "/etc/driver-manager.d/disabled" +ConditionPathExists = "!/etc/driver-manager.d/disabled" diff --git a/init/src/main.rs b/init/src/main.rs index 94162e61d3..275275e64b 100644 --- a/init/src/main.rs +++ b/init/src/main.rs @@ -14,7 +14,7 @@ mod script; mod service; mod unit; -use crate::color::{init_error, init_warn, status_fail, status_ok}; +use crate::color::{init_error, init_warn, status_ok}; fn switch_stdio(stdio: &str) -> io::Result<()> { let stdin = libredox::Fd::open(stdio, O_RDONLY, 0)?; diff --git a/init/src/scheduler.rs b/init/src/scheduler.rs index 8ee2771c25..58ef2e0687 100644 --- a/init/src/scheduler.rs +++ b/init/src/scheduler.rs @@ -109,6 +109,13 @@ fn run(unit: &mut Unit, config: &mut InitConfig) { status_skip(&format!("Skipping {} ({})", desc, service.cmd)); return; } + if !service.condition_met() { + status_skip(&format!( + "Skipping {} (ConditionPathExists not met)", + desc + )); + return; + } if config.log_debug { init_info(&format!("Starting {} ({})", desc, service.cmd)); } else { diff --git a/init/src/service.rs b/init/src/service.rs index 27d9ec0338..2646da7f46 100644 --- a/init/src/service.rs +++ b/init/src/service.rs @@ -1,7 +1,7 @@ use std::collections::{BTreeMap, BTreeSet}; use std::ffi::OsString; use std::fs::File; -use std::io::{self, Read, Write}; +use std::io::{self, Read}; use std::os::fd::{AsRawFd, FromRawFd, OwnedFd}; use std::os::unix::process::CommandExt; use std::process::Command; @@ -24,6 +24,8 @@ pub struct Service { pub inherit_envs: BTreeSet, #[serde(rename = "type")] pub type_: ServiceType, + #[serde(default, rename = "ConditionPathExists")] + pub condition_path_exists: Option, } #[derive(Clone, Debug, Default, Deserialize)] @@ -36,6 +38,21 @@ pub enum ServiceType { OneshotAsync, } +impl Service { + /// systemd-style ConditionPathExists gate. A leading `!` negates the + /// test: the service starts only when the path does NOT exist. + pub fn condition_met(&self) -> bool { + let Some(cond) = &self.condition_path_exists else { + return true; + }; + let (negated, path) = match cond.strip_prefix('!') { + Some(rest) => (true, rest), + None => (false, cond.as_str()), + }; + std::path::Path::new(path).exists() != negated + } +} + fn create_pipe() -> io::Result<(File, OwnedFd)> { let mut fds = [0i32; 2]; // Use libc::pipe2() which goes through relibc's FILETABLE-managed path