1use std::{fmt, str::FromStr};
2use sys_mount::FilesystemType as MountFS;
3
4#[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#[derive(Debug)]
24pub enum PartitionSizeError {
25 TooSmall(u64, u64),
26 TooLarge(u64, u64),
27}
28
29impl FileSystem {
30 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
123impl 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}