use std::borrow::{Borrow, Cow}; use std::error::Error; use std::fmt; use std::fs; use std::os::unix::fs::MetadataExt; use std::path::Path; use users::get_user_by_name; use command_runner::CommandRunner; use resources::Resource; use symbols::{Action, OwnedSymbolAction, Symbol, SymbolAction, SymbolRunner}; pub struct Owner<'a, C: 'a + CommandRunner, D> where D: AsRef, { path: D, user_name: Cow<'a, str>, command_runner: &'a C, } impl<'a, C: CommandRunner, D> Owner<'a, C, D> where D: AsRef, { pub fn new(path: D, user_name: Cow<'a, str>, command_runner: &'a C) -> Self { Owner { path, user_name, command_runner, } } } impl<'a, C: CommandRunner, D> Symbol for Owner<'a, C, D> where D: AsRef, { fn target_reached(&self) -> Result> { if !Path::new(self.path.as_ref()).exists() { return Ok(false); } let actual_uid = fs::metadata(self.path.as_ref()).unwrap().uid(); let target_uid = get_user_by_name(self.user_name.borrow()).unwrap().uid(); Ok(actual_uid == target_uid) } fn execute(&self) -> Result<(), Box> { self.command_runner.run_successfully( "chown", &["-R", self.user_name.borrow(), self.path.as_ref()], ) } fn get_prerequisites(&self) -> Vec { vec![Resource::new("user", self.user_name.to_string())] } fn as_action<'b>(&'b self, runner: &'b dyn SymbolRunner) -> Box { Box::new(SymbolAction::new(runner, self)) } fn into_action<'b>(self: Box, runner: &'b dyn SymbolRunner) -> Box where Self: 'b, { Box::new(OwnedSymbolAction::new(runner, *self)) } } impl<'a, C: CommandRunner, D> fmt::Display for Owner<'a, C, D> where D: AsRef, { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { write!(f, "Owner {} for {}", self.user_name, self.path.as_ref()) } }