Skip to content
88 changes: 75 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ fn systemctl_capture(args: Vec<&str>) -> std::io::Result<String> {
}
} else {
Err(Error::new(ErrorKind::InvalidData, "systemctl stdout empty"))
}
}
/*},
false => {
Err(Error::new(ErrorKind::Other,
Expand Down Expand Up @@ -135,7 +135,7 @@ pub fn list_units(
for l in lines.skip(1) {
// header labels
let parsed: Vec<_> = l.split_ascii_whitespace().collect();
if parsed.len() == 2 {
if parsed.len() >= 2 {
result.push(parsed[0].to_string())
}
}
Expand All @@ -154,17 +154,53 @@ pub fn list_enabled_services() -> std::io::Result<Vec<String>> {

/// `AutoStartStatus` describes the Unit current state
#[derive(Copy, Clone, PartialEq, Eq, EnumString, Debug)]
pub enum AutoStartStatus {
#[strum(serialize = "static")]
Static,
#[strum(serialize = "enabled")]
Enabled,
#[strum(serialize = "disabled")]
Disabled,
#[strum(serialize = "generated")]
Generated,
#[strum(serialize = "indirect")]
Indirect,
pub enum Type {
#[strum(serialize = "automount")]
AutoMount,
#[strum(serialize = "mount")]
Mount,
#[strum(serialize = "service")]
Service,
#[strum(serialize = "scope")]
Scope,
#[strum(serialize = "socket")]
Socket,
#[strum(serialize = "slice")]
Slice,
#[strum(serialize = "timer")]
Timer,
#[strum(serialize = "path")]
Path,
#[strum(serialize = "target")]
Target,
#[strum(serialize = "swap")]
Swap,
#[strum(serialize = "aa-prompt-listener")]
AaPromptListener,
#[strum(serialize = "system-shutdown")]
SystemShutdown,
#[strum(serialize = "recovery-chooser-trigger")]
RecoveryChooserTrigger,
#[strum(serialize = "failure")]
Failure,
#[strum(serialize = "unmount")]
Unmount,
#[strum(serialize = "autoimport")]
AutoImport,
#[strum(serialize = "snap-repair")]
SnapRepair,
#[strum(serialize = "mounts-pre")]
MountsPre,
#[strum(serialize = "mounts-post")]
MountsPost,
#[strum(serialize = "mounts")]
Mounts,
#[strum(serialize = "seeded")]
Seeded,
#[strum(serialize = "apparmor")]
Apparmor,
#[strum(serialize = "core-fixup")]
CoreFixup,
}

impl Default for AutoStartStatus {
Expand Down Expand Up @@ -194,6 +230,8 @@ pub enum Type {
Path,
#[strum(serialize = "target")]
Target,
#[strum(serialize = "swap")]
Swap,
}

impl Default for Type {
Expand Down Expand Up @@ -452,6 +490,7 @@ impl Unit {
let (rem, _) = rem.split_at(rem.len() - 1); // remove ")"
let items: Vec<_> = rem.split_terminator(";").collect();
script = items[0].trim().to_string();

auto_start = AutoStartStatus::from_str(items[1].trim()).unwrap();
if items.len() > 2 {
// preset is optionnal ?
Expand Down Expand Up @@ -657,6 +696,8 @@ impl Unit {
}
}



#[cfg(test)]
mod test {
use super::*;
Expand Down Expand Up @@ -706,21 +747,42 @@ mod test {
let unit = Unit::from_systemctl("non-existing");
assert_eq!(unit.is_err(), true);
}

//Auxiliar function for next test
fn contains_numbers(s: &str) -> bool {
for c in s.chars() {
if c.is_numeric() {
return true;
}
}
false
}

#[test]
fn test_service_unit_construction() {
let units = list_units(None, None).unwrap(); // all units
assert_eq!(units.len() > 0, true);
for unit in units {
let unit = unit.as_str();
if unit.contains("@") {
// not testing this one
// would require @x service # identification / enumeration
continue;
}
if contains_numbers(&unit) {
//if you try to unwrap a unit with a name containing numbers it will give out an error
//for now this is a quick fix to avoid that
//this problem needs to be looked in to in detail
continue;
}

let c0 = unit.chars().nth(0).unwrap();
if c0.is_alphanumeric() {
// valid unit name --> run test
println!("Unit: {:?}", &unit);
let u = Unit::from_systemctl(&unit).unwrap();
println!("####################################");

println!("Unit: {:#?}", u);
println!("active: {}", u.active);
println!("preset: {}", u.preset);
Expand Down