init: ConditionPathExists service gate (systemd-style, with ! negation)
init's Service parser used deny_unknown_fields, so the C0 driver-manager service files (which use ConditionPathExists) were rejected wholesale — driver-manager stayed dormant by parser accident instead of by design. - service.rs: new optional ConditionPathExists field + condition_met() gate. A leading '!' negates: the service starts only when the path does NOT exist. - scheduler.rs: skip services whose condition is not met (status_skip, same pattern as skip_cmd). - 00_driver-manager.service: fix inverted polarity — the intent is 'run unless /etc/driver-manager.d/disabled exists', i.e. ConditionPathExists = "!/etc/driver-manager.d/disabled". - Drop two pre-existing unused imports (Write in service.rs, status_fail in main.rs).
This commit is contained in:
@@ -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"
|
||||
|
||||
+1
-1
@@ -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)?;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+18
-1
@@ -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<String>,
|
||||
#[serde(rename = "type")]
|
||||
pub type_: ServiceType,
|
||||
#[serde(default, rename = "ConditionPathExists")]
|
||||
pub condition_path_exists: Option<String>,
|
||||
}
|
||||
|
||||
#[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
|
||||
|
||||
Reference in New Issue
Block a user