~iptq/garbage

ref: 02ba29053be29149ec4ca4f73cd375f02f2cf21b garbage/src/mounts.rs -rw-r--r-- 1.8 KiB
02ba2905Michael Zhang fix panic problem by not converting to utf-8 all the time 1 year, 5 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use std::borrow::Cow;
use std::ffi::OsStr;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

use anyhow::Error;
use libmount::mountinfo::Parser;

use crate::utils;

#[derive(Debug)]
pub struct MountPoint {
    pub mount_id: u64,
    pub parent_id: u64,
    pub major: u64,
    pub minor: u64,
    pub root: PathBuf,
    pub mount_point: PathBuf,
}

fn get_path(s: Cow<OsStr>) -> PathBuf {
    Path::new(&s).to_path_buf()
}

impl From<libmount::mountinfo::MountPoint<'_>> for MountPoint {
    fn from(mp: libmount::mountinfo::MountPoint) -> Self {
        MountPoint {
            mount_id: mp.mount_id,
            parent_id: mp.parent_id,
            major: mp.major,
            minor: mp.minor,
            root: get_path(mp.root),
            mount_point: get_path(mp.mount_point),
        }
    }
}

#[derive(Debug)]
pub struct Mounts(Vec<MountPoint>);

impl Mounts {
    pub fn read() -> Result<Mounts, Error> {
        let pid = unsafe { libc::getpid() };
        let path = Path::new("/")
            .join("proc")
            .join(pid.to_string())
            .join("mountinfo");

        let mut buf = Vec::new();
        {
            let mut file = File::open(path)?;
            file.read_to_end(&mut buf)?;
        }

        let parser = Parser::new(&buf);
        let mut mounts = Vec::new();

        for mp in parser {
            let mp = mp?;
            mounts.push(MountPoint::from(mp));
        }

        Ok(Mounts(mounts))
    }

    pub fn get_mount_point(&self, path: impl AsRef<Path>) -> Option<PathBuf> {
        let path = utils::into_absolute(path).ok()?;

        self.0
            .iter()
            .filter(|mp| path.starts_with(&mp.mount_point))
            .max_by_key(|mp| mp.mount_point.components().count())
            .map(|mp| mp.mount_point.to_path_buf())
    }
}