systemd_boot_conf/
loader.rs

1use 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}