systemd_boot_conf/
loader.rs1use std::fs::File;
2use std::io::{self, BufRead, BufReader};
3use std::path::Path;
4
5#[derive(Debug, Error)]
6pub enum LoaderError {
7 #[error("error reading line in loader conf")]
8 Line(#[source] io::Error),
9 #[error("loader conf is not a file")]
10 NotAFile,
11 #[error("default was defined without a value")]
12 NoValueForDefault,
13 #[error("timeout was defined without a value")]
14 NoValueForTimeout,
15 #[error("error opening loader file")]
16 Open(#[source] io::Error),
17 #[error("timeout was defined with a value ({}) which is not a number", _0)]
18 TimeoutNaN(String),
19}
20
21#[derive(Debug, Default, Clone)]
22pub struct LoaderConf {
23 pub default: Option<Box<str>>,
24 pub timeout: Option<u32>,
25}
26
27impl LoaderConf {
28 pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Self, LoaderError> {
29 let path = path.as_ref();
30
31 let mut loader = LoaderConf::default();
32 if !path.exists() {
33 return Ok(loader);
34 }
35
36 if !path.is_file() {
37 return Err(LoaderError::NotAFile);
38 }
39
40 let file = File::open(path).map_err(LoaderError::Open)?;
41
42 for line in BufReader::new(file).lines() {
43 let line = line.map_err(LoaderError::Line)?;
44 let mut fields = line.split_whitespace();
45 match fields.next() {
46 Some("default") => match fields.next() {
47 Some(default) => loader.default = Some(default.into()),
48 None => return Err(LoaderError::NoValueForDefault),
49 },
50 Some("timeout") => match fields.next() {
51 Some(timeout) => {
52 if let Ok(timeout) = timeout.parse::<u32>() {
53 loader.timeout = Some(timeout);
54 } else {
55 return Err(LoaderError::TimeoutNaN(timeout.into()));
56 }
57 }
58 None => return Err(LoaderError::NoValueForTimeout),
59 },
60 _ => (),
61 }
62 }
63
64 Ok(loader)
65 }
66}