use std::{
fs,
path::{Path, PathBuf},
};
use thiserror::Error;
pub mod config;
pub mod entry;
mod macros;
use crate::macros::generate_builder_method;
pub use config::{Config, ConfigBuilder};
pub use entry::{Entry, EntryBuilder, Token};
#[derive(Error, Debug)]
pub enum LibSDBootConfError {
#[error("invalid configuration")]
ConfigParseError,
#[error("invalid entry")]
EntryParseError,
#[error("invalid entry filename {0}")]
InvalidEntryFilename(PathBuf),
#[error(transparent)]
IOError(#[from] std::io::Error),
#[error("invalid token {0}")]
InvalidToken(String),
}
#[derive(Default, Debug)]
pub struct SystemdBootConf {
pub working_dir: PathBuf,
pub esp: PathBuf,
pub config: Config,
pub entries: Vec<Entry>,
}
impl SystemdBootConf {
pub fn new<P, C, E>(working_dir: P, esp: P, config: C, entries: E) -> Self
where
P: Into<PathBuf>,
C: Into<Config>,
E: Into<Vec<Entry>>,
{
Self {
working_dir: working_dir.into(),
esp: esp.into(),
config: config.into(),
entries: entries.into(),
}
}
pub fn init<P: Into<PathBuf>>(working_dir: P, esp: P) -> Self {
Self {
working_dir: working_dir.into(),
esp: esp.into(),
..Default::default()
}
}
pub fn load<P: AsRef<Path>>(working_dir: P, esp: P) -> Result<Self, LibSDBootConfError> {
let mut systemd_boot_conf = Self::init(working_dir.as_ref(), esp.as_ref());
systemd_boot_conf.load_current()?;
Ok(systemd_boot_conf)
}
pub fn load_current(&mut self) -> Result<(), LibSDBootConfError> {
let config = Config::load(self.esp.join("loader").join("loader.conf"))?;
let mut entries = Vec::new();
for file in fs::read_dir(self.working_dir.join("entries"))? {
let path = file?.path();
if path.is_file() {
let entry = Entry::load(&path)?;
entries.push(entry);
}
}
self.config = config;
self.entries = entries;
Ok(())
}
pub fn write_config(&self) -> Result<(), LibSDBootConfError> {
self.config
.write(self.esp.join("loader").join("loader.conf"))?;
Ok(())
}
pub fn write_entries(&self) -> Result<(), LibSDBootConfError> {
for entry in self.entries.iter() {
entry.write(
self.working_dir
.join("entries")
.join(format!("{}.conf", entry.id)),
)?;
}
Ok(())
}
pub fn write_all(&self) -> Result<(), LibSDBootConfError> {
self.write_config()?;
self.write_entries()?;
Ok(())
}
}
#[derive(Default, Debug)]
pub struct SystemdBootConfBuilder {
inner: SystemdBootConf,
}
impl SystemdBootConfBuilder {
pub fn new<P: Into<PathBuf>>(working_dir: P, esp: P) -> Self {
Self {
inner: SystemdBootConf::init(working_dir, esp),
}
}
generate_builder_method!(
plain INNER(inner) config(Config)
);
generate_builder_method!(
into INNER(inner) entries(E: Vec<Entry>)
);
pub fn entry(mut self, entry: Entry) -> Self {
self.inner.entries.push(entry);
self
}
pub fn build(self) -> SystemdBootConf {
self.inner
}
}