use super::FixAction;
#[must_use]
pub fn render_command(action: &FixAction) -> String {
match action {
FixAction::Chmod { path, mode_change } => {
format!("chmod {} {}", mode_change, quote_path(path))
}
FixAction::Chown { path, owner, group } => render_chown(path, *owner, *group),
FixAction::SetAcl { path, entry } => {
format!("setfacl -m {} {}", entry, quote_path(path))
}
FixAction::Remount {
mountpoint,
options,
} => {
format!("mount -o remount,{} {}", options, quote_path(mountpoint))
}
FixAction::Chattr { path, flags } => {
format!("chattr {} {}", flags, quote_path(path))
}
FixAction::GrantCap { path, capability } => render_grant_cap(path.as_deref(), capability),
}
}
fn render_chown(path: &std::path::Path, owner: Option<u32>, group: Option<u32>) -> String {
let spec = match (owner, group) {
(Some(u), Some(g)) => format!("{u}:{g}"),
(Some(u), None) => format!("{u}"),
(None, Some(g)) => format!(":{g}"),
(None, None) => String::new(),
};
format!("chown {} {}", spec, quote_path(path))
}
fn render_grant_cap(path: Option<&std::path::Path>, capability: &str) -> String {
match path {
Some(p) => format!("setcap {capability}+ep {}", quote_path(p)),
None => format!("setcap {capability}+ep <executable> (pass --executable to specify)"),
}
}
fn quote_path(path: &std::path::Path) -> String {
let s = path.display().to_string();
if s.contains(' ') || s.contains('\'') || s.contains('"') {
format!("'{}'", s.replace('\'', "'\\''"))
} else {
s
}
}
#[cfg(test)]
#[path = "commands_tests.rs"]
mod tests;