1use anyhow::{bail, Result};
2use std::fs;
3use std::path::{Path, PathBuf};
4use std::rc::Rc;
5
6#[derive(Debug, PartialEq, Eq)]
7pub struct Mount {
8 pub device: String,
9 pub mountpoint: PathBuf,
10 pub fs: String,
11 pub options: Vec<String>,
12 pub dump_level: u8,
13 pub fsck_passno: u8,
14}
15
16pub fn parse_mtab_line(string: &str) -> Result<Mount> {
17 let mut fields = string.split_ascii_whitespace();
18 macro_rules! next {
19 (expecting $lit:literal) => {
20 if let Some(field) = fields.next() {
21 field
22 } else {
23 bail!("expected {}\n, but got EOL", $lit);
24 }
25 };
26 }
27
28 let device = next!(expecting "a device").to_string();
29 let mountpoint = PathBuf::from(next!(expecting "a mountpoint"));
30 let fs = next!(expecting "a filesystem type").to_string();
31 let options = next!(expecting "a list of options")
32 .split(',')
33 .map(str::to_string)
34 .collect();
35 let dump_level = next!(expecting "an integer").parse()?;
36 let fsck_passno = next!(expecting "an integer").parse()?;
37
38 let mount = Mount {
39 device,
40 mountpoint,
41 fs,
42 options,
43 dump_level,
44 fsck_passno,
45 };
46
47 Ok(mount)
48}
49
50pub fn read_mtab_from<P: AsRef<Path>>(path: P) -> Result<Rc<[Mount]>> {
51 let lines: Result<Rc<[_]>> = fs::read_to_string(path.as_ref())?
52 .lines()
53 .map(parse_mtab_line)
54 .collect();
55 let lines = lines?;
56 Ok(lines)
57}
58
59pub fn read_mtab() -> Result<Rc<[Mount]>> {
60 read_mtab_from("/etc/mtab")
61}
62
63#[cfg(test)]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn it_works() {
69 let line = "/dev/sda1 /mnt/indarys ext4 rw,nosuid,nodev 1 2";
70 let parsed_mount = parse_mtab_line(line).expect("should be parseable");
71 let manual_mount = Mount {
72 device: "/dev/sda1".to_string(),
73 mountpoint: PathBuf::from("/mnt/indarys"),
74 fs: "ext4".to_string(),
75 options: vec!["rw".to_string(), "nosuid".to_string(), "nodev".to_string()],
76 dump_level: 1,
77 fsck_passno: 2,
78 };
79 assert_eq!(parsed_mount, manual_mount);
80 }
81
82 #[cfg(unix)]
83 #[test]
84 fn it_really_works() {
85 assert!(read_mtab().is_ok())
86 }
87}