Skip to content

Commit dd04563

Browse files
committed
partitioning: Add new formatter trait for building Commands to format disks
Signed-off-by: Ikey Doherty <[email protected]>
1 parent 8668f02 commit dd04563

File tree

2 files changed

+198
-0
lines changed

2 files changed

+198
-0
lines changed

crates/partitioning/src/formatter.rs

+195
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
// SPDX-FileCopyrightText: Copyright © 2025 AerynOS Developers
2+
//
3+
// SPDX-License-Identifier: MPL-2.0
4+
5+
use std::{path::Path, process::Command};
6+
7+
use types::Filesystem;
8+
9+
/// Trait for generating filesystem-specific formatting commands and arguments
10+
pub trait FilesystemExt {
11+
/// Returns the appropriate mkfs command for the filesystem
12+
fn mkfs_command(&self) -> &str;
13+
14+
/// Returns the command-line arguments for setting UUID, if applicable
15+
fn uuid_arg(&self) -> Vec<String>;
16+
17+
/// Returns the command-line arguments for setting filesystem label, if applicable
18+
fn label_arg(&self) -> Vec<String>;
19+
20+
/// Returns the force format argument if applicable
21+
fn force_arg(&self) -> Vec<String>;
22+
}
23+
24+
impl FilesystemExt for Filesystem {
25+
fn mkfs_command(&self) -> &str {
26+
match self {
27+
Filesystem::Fat32 { .. } => "mkfs.fat",
28+
Filesystem::Standard { filesystem_type, .. } => match filesystem_type {
29+
types::StandardFilesystemType::F2fs => "mkfs.f2fs",
30+
types::StandardFilesystemType::Ext4 => "mkfs.ext4",
31+
types::StandardFilesystemType::Xfs => "mkfs.xfs",
32+
types::StandardFilesystemType::Swap => "mkswap",
33+
},
34+
Filesystem::Any => panic!("Cannot format with 'any' filesystem type"),
35+
}
36+
}
37+
38+
fn uuid_arg(&self) -> Vec<String> {
39+
match self {
40+
Filesystem::Fat32 { volume_id, .. } => {
41+
if let Some(id) = volume_id {
42+
vec!["-i".to_string(), id.to_string()]
43+
} else {
44+
vec![]
45+
}
46+
}
47+
Filesystem::Standard {
48+
filesystem_type, uuid, ..
49+
} => {
50+
if let Some(uuid) = uuid {
51+
match filesystem_type {
52+
types::StandardFilesystemType::Ext4 => vec!["-U".to_string(), uuid.to_string()],
53+
types::StandardFilesystemType::F2fs => vec!["-U".to_string(), uuid.to_string()],
54+
types::StandardFilesystemType::Xfs => vec!["-m".to_string(), format!("uuid={}", uuid)],
55+
types::StandardFilesystemType::Swap => vec!["-U".to_string(), uuid.to_string()],
56+
}
57+
} else {
58+
vec![]
59+
}
60+
}
61+
Filesystem::Any => vec![],
62+
}
63+
}
64+
65+
fn label_arg(&self) -> Vec<String> {
66+
match self {
67+
Filesystem::Fat32 { label, .. } => {
68+
if let Some(label) = label {
69+
vec!["-n".to_string(), label.to_string()]
70+
} else {
71+
vec![]
72+
}
73+
}
74+
Filesystem::Standard {
75+
filesystem_type, label, ..
76+
} => {
77+
if let Some(label) = label {
78+
match filesystem_type {
79+
types::StandardFilesystemType::Ext4 => vec!["-L".to_string(), label.to_string()],
80+
types::StandardFilesystemType::F2fs => vec!["-l".to_string(), label.to_string()],
81+
types::StandardFilesystemType::Xfs => vec!["-L".to_string(), label.to_string()],
82+
types::StandardFilesystemType::Swap => vec!["-L".to_string(), label.to_string()],
83+
}
84+
} else {
85+
vec![]
86+
}
87+
}
88+
Filesystem::Any => panic!("Cannot format with 'any' filesystem type"),
89+
}
90+
}
91+
92+
fn force_arg(&self) -> Vec<String> {
93+
match self {
94+
Filesystem::Fat32 { .. } => vec![],
95+
Filesystem::Standard { filesystem_type, .. } => match filesystem_type {
96+
types::StandardFilesystemType::F2fs => vec!["-f".to_string()],
97+
types::StandardFilesystemType::Ext4 => vec!["-F".to_string()],
98+
types::StandardFilesystemType::Xfs => vec!["-f".to_string()],
99+
types::StandardFilesystemType::Swap => vec!["-f".to_string()],
100+
},
101+
Filesystem::Any => vec![],
102+
}
103+
}
104+
}
105+
106+
/// Struct for formatting filesystems on devices
107+
pub struct Formatter {
108+
pub filesystem: Filesystem,
109+
pub force: bool,
110+
}
111+
112+
impl Formatter {
113+
/// Creates a new Formatter for the given filesystem
114+
pub fn new(filesystem: Filesystem) -> Self {
115+
Self {
116+
filesystem,
117+
force: false,
118+
}
119+
}
120+
121+
/// Creates a new Formatter with force enabled
122+
pub fn force(filesystem: Filesystem) -> Self {
123+
Self {
124+
filesystem,
125+
force: true,
126+
}
127+
}
128+
129+
/// Returns a Command configured to format the given device with the filesystem
130+
pub fn format(&self, device: &Path) -> Command {
131+
let mut cmd = Command::new(self.filesystem.mkfs_command());
132+
133+
cmd.args(self.filesystem.uuid_arg());
134+
cmd.args(self.filesystem.label_arg());
135+
if self.force {
136+
cmd.args(self.filesystem.force_arg());
137+
}
138+
139+
cmd.arg(device);
140+
cmd
141+
}
142+
}
143+
144+
#[cfg(test)]
145+
mod tests {
146+
use super::*;
147+
use uuid::Uuid;
148+
149+
#[test]
150+
fn test_fat32_args() {
151+
let fs = Filesystem::Fat32 {
152+
label: Some("BOOT".to_string()),
153+
volume_id: Some(1234),
154+
};
155+
156+
assert_eq!(fs.mkfs_command(), "mkfs.fat");
157+
assert_eq!(fs.uuid_arg(), vec!["-i", "1234"]);
158+
assert_eq!(fs.label_arg(), vec!["-n", "BOOT"]);
159+
}
160+
161+
#[test]
162+
fn test_ext4_args() {
163+
let uuid = Uuid::new_v4();
164+
let fs = Filesystem::Standard {
165+
filesystem_type: types::StandardFilesystemType::Ext4,
166+
label: Some("root".to_string()),
167+
uuid: Some(uuid.to_string()),
168+
};
169+
170+
assert_eq!(fs.mkfs_command(), "mkfs.ext4");
171+
assert_eq!(fs.uuid_arg(), vec!["-U".to_string(), uuid.to_string()]);
172+
assert_eq!(fs.label_arg(), vec!["-L", "root"]);
173+
}
174+
175+
#[test]
176+
fn test_xfs_args() {
177+
let uuid = Uuid::new_v4();
178+
let fs = Filesystem::Standard {
179+
filesystem_type: types::StandardFilesystemType::Xfs,
180+
label: Some("data".to_string()),
181+
uuid: Some(uuid.to_string()),
182+
};
183+
184+
assert_eq!(fs.mkfs_command(), "mkfs.xfs");
185+
assert_eq!(fs.uuid_arg(), vec!["-m".to_string(), format!("uuid={}", uuid)]);
186+
assert_eq!(fs.label_arg(), vec!["-L", "data"]);
187+
}
188+
189+
#[test]
190+
#[should_panic(expected = "Cannot format with 'any' filesystem type")]
191+
fn test_any_filesystem_panic() {
192+
let fs = Filesystem::Any;
193+
fs.mkfs_command();
194+
}
195+
}

crates/partitioning/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ pub mod sparsefile;
99
mod attributes;
1010
pub use attributes::*;
1111

12+
mod formatter;
13+
pub use formatter::*;
14+
1215
pub use gpt;
1316

1417
pub mod planner;

0 commit comments

Comments
 (0)