use crate::config_file::ConfigFile;
use crate::error::IoError;
use std::fs;
use std::io::Read;
use std::path::Path;
pub const SELINUX_CONFIG_PATH: &str = "/etc/selinux/config";
impl ConfigFile {
pub fn read_from(path: impl AsRef<Path>) -> Result<Self, IoError> {
let path = path.as_ref();
let mut file = fs::File::open(path).map_err(|e| IoError {
path: path.to_path_buf(),
source: e,
})?;
let mut content = String::new();
file.read_to_string(&mut content).map_err(|e| IoError {
path: path.to_path_buf(),
source: e,
})?;
ConfigFile::parse(&content).map_err(|e| IoError {
path: path.to_path_buf(),
source: std::io::Error::new(std::io::ErrorKind::InvalidData, e.to_string()),
})
}
pub fn read_default() -> Result<Self, IoError> {
let path = Path::new(SELINUX_CONFIG_PATH);
match Self::read_from(path) {
Ok(cfg) => Ok(cfg),
Err(e) => {
if e.source.kind() == std::io::ErrorKind::NotFound {
Ok(ConfigFile::new())
} else {
Err(e)
}
}
}
}
pub fn write_to(&self, path: impl AsRef<Path>) -> Result<(), IoError> {
let path = path.as_ref();
let content = self.to_string();
let tmp_name = format!(
".{}.tmp",
path.file_name()
.and_then(|n| n.to_str())
.unwrap_or("config")
);
let tmp_path = path.with_file_name(tmp_name);
fs::write(&tmp_path, &content).map_err(|e| IoError {
path: tmp_path.clone(),
source: e,
})?;
let tmp_file = fs::File::open(&tmp_path).map_err(|e| IoError {
path: tmp_path.clone(),
source: e,
})?;
tmp_file.sync_all().map_err(|e| IoError {
path: tmp_path.clone(),
source: e,
})?;
fs::rename(&tmp_path, path).map_err(|e| IoError {
path: path.to_path_buf(),
source: e,
})?;
if let Some(parent) = path.parent() {
let dir = fs::File::open(parent).map_err(|e| IoError {
path: parent.to_path_buf(),
source: e,
})?;
dir.sync_all().map_err(|e| IoError {
path: parent.to_path_buf(),
source: e,
})?;
}
Ok(())
}
pub fn write_default(&self) -> Result<(), IoError> {
self.write_to(SELINUX_CONFIG_PATH)
}
}