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"
|
type = "oneshot_async"
|
||||||
# Operator must explicitly enable this service:
|
# Operator must explicitly enable this service:
|
||||||
# touch /etc/driver-manager.d/disabled # force fallback to pcid-spawner
|
# 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 service;
|
||||||
mod unit;
|
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<()> {
|
fn switch_stdio(stdio: &str) -> io::Result<()> {
|
||||||
let stdin = libredox::Fd::open(stdio, O_RDONLY, 0)?;
|
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));
|
status_skip(&format!("Skipping {} ({})", desc, service.cmd));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if !service.condition_met() {
|
||||||
|
status_skip(&format!(
|
||||||
|
"Skipping {} (ConditionPathExists not met)",
|
||||||
|
desc
|
||||||
|
));
|
||||||
|
return;
|
||||||
|
}
|
||||||
if config.log_debug {
|
if config.log_debug {
|
||||||
init_info(&format!("Starting {} ({})", desc, service.cmd));
|
init_info(&format!("Starting {} ({})", desc, service.cmd));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+18
-1
@@ -1,7 +1,7 @@
|
|||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::fs::File;
|
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::fd::{AsRawFd, FromRawFd, OwnedFd};
|
||||||
use std::os::unix::process::CommandExt;
|
use std::os::unix::process::CommandExt;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
@@ -24,6 +24,8 @@ pub struct Service {
|
|||||||
pub inherit_envs: BTreeSet<String>,
|
pub inherit_envs: BTreeSet<String>,
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub type_: ServiceType,
|
pub type_: ServiceType,
|
||||||
|
#[serde(default, rename = "ConditionPathExists")]
|
||||||
|
pub condition_path_exists: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Deserialize)]
|
#[derive(Clone, Debug, Default, Deserialize)]
|
||||||
@@ -36,6 +38,21 @@ pub enum ServiceType {
|
|||||||
OneshotAsync,
|
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)> {
|
fn create_pipe() -> io::Result<(File, OwnedFd)> {
|
||||||
let mut fds = [0i32; 2];
|
let mut fds = [0i32; 2];
|
||||||
// Use libc::pipe2() which goes through relibc's FILETABLE-managed path
|
// Use libc::pipe2() which goes through relibc's FILETABLE-managed path
|
||||||
|
|||||||
Reference in New Issue
Block a user