nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 103 lines 3.7 kB view raw
1use std::fs; 2 3use anyhow::{Context, Result}; 4 5pub struct Mounts { 6 inner: Vec<Mount>, 7} 8 9#[derive(Debug)] 10pub struct Mount { 11 _spec: String, 12 file: String, 13 _vfstype: String, 14 pub mntopts: MntOpts, 15} 16 17#[derive(Debug)] 18pub struct MntOpts { 19 inner: Vec<String>, 20} 21 22impl Mounts { 23 pub fn parse_from_proc_mounts() -> Result<Self> { 24 let proc_mounts = 25 fs::read_to_string("/proc/mounts").context("Failed to read /proc/mounts")?; 26 Self::parse(&proc_mounts) 27 } 28 29 fn parse(s: &str) -> Result<Self> { 30 let mut inner = Vec::new(); 31 for line in s.lines() { 32 let mut split = line.split_whitespace(); 33 let mount = Mount { 34 _spec: split.next().context("Failed to parse spec")?.to_string(), 35 file: split.next().context("Failed to parse file")?.to_string(), 36 _vfstype: split.next().context("Failed to parse vfstype")?.to_string(), 37 mntopts: MntOpts::parse(split.next().context("Failed to parse mntopts")?), 38 }; 39 inner.push(mount); 40 } 41 Ok(Self { inner }) 42 } 43 44 pub fn find_mountpoint(&self, mountpoint: &str) -> Option<&Mount> { 45 self.inner.iter().rev().find(|m| m.file == mountpoint) 46 } 47} 48 49impl MntOpts { 50 fn parse(s: &str) -> Self { 51 let mut vec = Vec::new(); 52 for sp in s.split(',') { 53 vec.push(sp.to_string()); 54 } 55 56 Self { inner: vec } 57 } 58 59 pub fn contains(&self, s: &str) -> bool { 60 self.inner.contains(&s.to_string()) 61 } 62} 63 64#[cfg(test)] 65mod tests { 66 use super::*; 67 68 use indoc::indoc; 69 70 #[test] 71 fn test_proc_mounts_parsing() -> Result<()> { 72 let s = indoc! {r" 73 /dev/mapper/root / btrfs rw,noatime,compress=zstd:3,ssd,discard=async,space_cache=v2,subvolid=5,subvol=/ 0 0 74 tmpfs /run tmpfs rw,nosuid,nodev,size=15350916k,nr_inodes=819200,mode=755 0 0 75 devtmpfs /dev devtmpfs rw,nosuid,size=3070184k,nr_inodes=7671201,mode=755 0 0 76 devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=3,mode=620,ptmxmode=666 0 0 77 tmpfs /dev/shm tmpfs rw,nosuid,nodev 0 0 78 proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0 79 ramfs /run/keys ramfs rw,nosuid,nodev,relatime,mode=750 0 0 80 sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0 81 /dev/mapper/root /nix/store btrfs ro,nosuid,nodev,noatime,compress=zstd:3,ssd,discard=async,space_cache=v2,subvolid=5,subvol=/ 0 0 82 securityfs /sys/kernel/security securityfs rw,nosuid,nodev,noexec,relatime 0 0 83 cgroup2 /sys/fs/cgroup cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate,memory_recursiveprot 0 0 84 none /sys/fs/pstore pstore rw,nosuid,nodev,noexec,relatime 0 0 85 efivarfs /sys/firmware/efi/efivars efivarfs rw,nosuid,nodev,noexec,relatime 0 0 86 bpf /sys/fs/bpf bpf rw,nosuid,nodev,noexec,relatime,mode=700 0 0 87 hugetlbfs /dev/hugepages hugetlbfs rw,nosuid,nodev,relatime,pagesize=2M 0 0 88 mqueue /dev/mqueue mqueue rw,nosuid,nodev,noexec,relatime 0 0 89 debugfs /sys/kernel/debug debugfs rw,nosuid,nodev,noexec,relatime 0 0 90 tracefs /sys/kernel/tracing tracefs rw,nosuid,nodev,noexec,relatime 0 0 91 "}; 92 93 let mounts = Mounts::parse(s)?; 94 if let Some(nix_store_mount) = mounts.find_mountpoint("/nix/store") { 95 println!("{nix_store_mount:?}"); 96 println!("{:?}", nix_store_mount.mntopts); 97 assert!(nix_store_mount.mntopts.contains("ro")); 98 assert!(!nix_store_mount.mntopts.contains("no")); 99 } 100 101 Ok(()) 102 } 103}