disk_types/
fs.rs

1use std::{fmt, str::FromStr};
2use sys_mount::FilesystemType as MountFS;
3
4/// Describes a file system format, such as ext4 or fat32.
5#[derive(Debug, PartialEq, Copy, Clone, Hash)]
6pub enum FileSystem {
7    Btrfs,
8    Exfat,
9    Ext2,
10    Ext3,
11    Ext4,
12    F2fs,
13    Fat16,
14    Fat32,
15    Ntfs,
16    Swap,
17    Xfs,
18    Luks,
19    Lvm,
20}
21
22/// Indicates that a partition is either too small or too large.
23#[derive(Debug)]
24pub enum PartitionSizeError {
25    TooSmall(u64, u64),
26    TooLarge(u64, u64),
27}
28
29impl FileSystem {
30    /// Check if a given size, in bytes, is valid for this file system.
31    ///
32    /// # Possible Values
33    /// - `Ok(())` indicates a valid partition size.
34    /// - `Err(PartitionSizeError::TooSmall)` for a partition that is too small.
35    /// - `Err(PartitionSizeError::TooLarge)` for a partition that is too large.
36    pub fn validate_size(self, size: u64) -> Result<(), PartitionSizeError> {
37        const MIB: u64 = 1024 * 1024;
38        const GIB: u64 = MIB * 1024;
39        const TIB: u64 = GIB * 1024;
40
41        const FAT16_MIN: u64 = 16 * MIB;
42        const FAT16_MAX: u64 = (4096 - 1) * MIB;
43        const FAT32_MIN: u64 = 33 * MIB;
44        const FAT32_MAX: u64 = 2 * TIB;
45        const EXT4_MAX: u64 = 16 * TIB;
46        const BTRFS_MIN: u64 = 250 * MIB;
47
48        match self {
49            FileSystem::Btrfs if size < BTRFS_MIN => {
50                Err(PartitionSizeError::TooSmall(size, BTRFS_MIN))
51            }
52            FileSystem::Fat16 if size < FAT16_MIN => {
53                Err(PartitionSizeError::TooSmall(size, FAT16_MIN))
54            }
55            FileSystem::Fat16 if size > FAT16_MAX => {
56                Err(PartitionSizeError::TooLarge(size, FAT16_MAX))
57            }
58            FileSystem::Fat32 if size < FAT32_MIN => {
59                Err(PartitionSizeError::TooSmall(size, FAT32_MIN))
60            }
61            FileSystem::Fat32 if size > FAT32_MAX => {
62                Err(PartitionSizeError::TooLarge(size, FAT32_MAX))
63            }
64            FileSystem::Ext4 if size > EXT4_MAX => {
65                Err(PartitionSizeError::TooLarge(size, EXT4_MAX))
66            }
67            _ => Ok(()),
68        }
69    }
70}
71
72impl FromStr for FileSystem {
73    type Err = &'static str;
74
75    fn from_str(string: &str) -> Result<Self, Self::Err> {
76        let type_ = match string.to_lowercase().as_str() {
77            "btrfs" => FileSystem::Btrfs,
78            "exfat" => FileSystem::Exfat,
79            "ext2" => FileSystem::Ext2,
80            "ext3" => FileSystem::Ext3,
81            "ext4" => FileSystem::Ext4,
82            "f2fs" => FileSystem::F2fs,
83            "fat16" => FileSystem::Fat16,
84            "fat32" => FileSystem::Fat32,
85            "swap" | "linux-swap(v1)" => FileSystem::Swap,
86            "ntfs" => FileSystem::Ntfs,
87            "xfs" => FileSystem::Xfs,
88            "lvm" | "lvm2_member" => FileSystem::Lvm,
89            "luks" | "crypto_luks" => FileSystem::Luks,
90            _ => return Err("invalid file system name"),
91        };
92        Ok(type_)
93    }
94}
95
96impl Into<&'static str> for FileSystem {
97    fn into(self) -> &'static str {
98        match self {
99            FileSystem::Btrfs => "btrfs",
100            FileSystem::Exfat => "exfat",
101            FileSystem::Ext2 => "ext2",
102            FileSystem::Ext3 => "ext3",
103            FileSystem::Ext4 => "ext4",
104            FileSystem::F2fs => "f2fs",
105            FileSystem::Fat16 => "fat16",
106            FileSystem::Fat32 => "fat32",
107            FileSystem::Ntfs => "ntfs",
108            FileSystem::Swap => "linux-swap(v1)",
109            FileSystem::Xfs => "xfs",
110            FileSystem::Lvm => "lvm",
111            FileSystem::Luks => "luks",
112        }
113    }
114}
115
116impl fmt::Display for FileSystem {
117    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
118        let str: &'static str = (*self).into();
119        f.write_str(str)
120    }
121}
122
123/// Enable integration with the `sys_mount` crate, if it is used.
124impl From<FileSystem> for MountFS<'static> {
125    fn from(fs: FileSystem) -> Self {
126        MountFS::Manual(match fs {
127            FileSystem::Fat16 | FileSystem::Fat32 => "vfat",
128            fs => fs.into(),
129        })
130    }
131}