Skip to content

Commit 1725a18

Browse files
committed
disk-test: Add realistic automatic partitioning demo
This uses a new loopback device and sparse file, partitioning it on the fly. Signed-off-by: Ikey Doherty <[email protected]>
1 parent c48c090 commit 1725a18

File tree

2 files changed

+116
-14
lines changed

2 files changed

+116
-14
lines changed

disk-test/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ publish = false
66

77
[dependencies]
88
disks = { path = "../crates/disks" }
9+
log.workspace = true
910
partitioning = { path = "../crates/partitioning" }
11+
pretty_env_logger = "0.5.0"

disk-test/src/main.rs

Lines changed: 114 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,117 @@
22
//
33
// SPDX-License-Identifier: MPL-2.0
44

5-
use std::fs;
5+
use log::{debug, info};
6+
use std::{fs, path::Path};
67

78
use disks::BlockDevice;
8-
use partitioning::{loopback, sparsefile};
9+
use partitioning::{
10+
gpt::{disk::LogicalBlockSize, mbr::ProtectiveMBR, partition_types, GptConfig},
11+
loopback, sparsefile, sync_gpt_partitions,
12+
};
913

10-
// Demo of various disk APIs, enumeration, loopback and sparse.
14+
/// Creates a protective MBR on the specified disk
15+
///
16+
/// # Arguments
17+
///
18+
/// * `disk_size` - Size of the disk in bytes
19+
/// * `path` - Path to the disk device
20+
///
21+
/// # Returns
22+
///
23+
/// Result indicating success or error
24+
fn create_protective_mbr<P>(disk_size: u64, path: P) -> Result<(), Box<dyn std::error::Error>>
25+
where
26+
P: AsRef<Path>,
27+
{
28+
debug!("🛡️ Creating protective MBR for disk of size {} bytes", disk_size);
29+
let mut gpt_device = fs::File::options().write(true).open(&path)?;
30+
let lb_size = (disk_size / 512) as u32;
31+
let lb_size = lb_size.saturating_sub(1); // subtract 1 for the MBR
32+
let mbr = ProtectiveMBR::with_lb_size(lb_size);
33+
mbr.overwrite_lba0(&mut gpt_device)?;
34+
info!("✅ Successfully created protective MBR at {:?}", path.as_ref());
35+
Ok(())
36+
}
37+
38+
/// Creates a default GPT partition scheme on the disk with:
39+
/// - 256MB EFI System Partition
40+
/// - 2GB Boot Partition
41+
/// - 4GB Swap Partition
42+
/// - Remaining space as Linux filesystem
43+
///
44+
/// # Arguments
45+
///
46+
/// * `path` - Path to the disk device
47+
///
48+
/// # Returns
49+
///
50+
/// Result indicating success or error
51+
fn create_default_partition_scheme<P>(path: P) -> Result<(), Box<dyn std::error::Error>>
52+
where
53+
P: AsRef<Path>,
54+
{
55+
info!("💽 Creating default GPT partition scheme on {:?}", path.as_ref());
56+
57+
// Configure and create GPT disk
58+
let gpt_config = GptConfig::new()
59+
.writable(true)
60+
.logical_block_size(LogicalBlockSize::Lb512);
61+
62+
let mut gpt_disk = gpt_config.create(&path)?;
63+
64+
debug!("📝 Creating EFI System Partition (256MB)");
65+
gpt_disk.add_partition("", 256 * 1024 * 1024, partition_types::EFI, 0, None)?;
66+
67+
debug!("📝 Creating Boot Partition (2GB)");
68+
gpt_disk.add_partition("", 2 * 1024 * 1024 * 1024, partition_types::FREEDESK_BOOT, 0, None)?;
69+
70+
debug!("📝 Creating Swap Partition (4GB)");
71+
gpt_disk.add_partition("", 4 * 1024 * 1024 * 1024, partition_types::LINUX_SWAP, 0, None)?;
72+
73+
// Use remaining space for root partition
74+
let sectors = gpt_disk.find_free_sectors();
75+
debug!("📊 Available sectors: {sectors:?}");
76+
let (_, length) = sectors.iter().find(|(_, l)| *l > 0).unwrap();
77+
debug!("📝 Creating Root Partition ({}MB)", (length * 512) / (1024 * 1024));
78+
gpt_disk.add_partition("", *length * 512, partition_types::LINUX_FS, 0, None)?;
79+
let _ = gpt_disk.write()?;
80+
81+
info!("✅ Successfully created partition scheme");
82+
Ok(())
83+
}
84+
85+
/// Demonstrates usage of disk APIs including:
86+
/// - Creating sparse files
87+
/// - Setting up loopback devices
88+
/// - Partitioning with GPT
89+
/// - Enumerating block devices
1190
fn main() -> Result<(), Box<dyn std::error::Error>> {
12-
// create 35GB img, attach loopback
13-
sparsefile::create("hello.world", 35 * 1024 * 1024 * 1024)?;
91+
pretty_env_logger::formatted_builder()
92+
.filter_level(log::LevelFilter::Trace)
93+
.init();
94+
info!("🚀 Starting disk partitioning demo");
95+
96+
// Create 35GB sparse image file and attach to loopback device
97+
let image_size = 35 * 1024 * 1024 * 1024;
98+
info!("📁 Creating {}GB sparse image file", image_size / (1024 * 1024 * 1024));
99+
sparsefile::create("hello.world", image_size)?;
100+
101+
debug!("🔄 Setting up loopback device");
14102
let device = loopback::LoopDevice::create()?;
15103
device.attach("hello.world")?;
16-
eprintln!("loop device: {}", &device.path);
104+
info!("💫 Loop device created at: {}", &device.path);
105+
106+
// Initialize disk with protective MBR and partition scheme
107+
create_protective_mbr(image_size, "hello.world")?;
108+
create_default_partition_scheme("hello.world")?;
109+
110+
// Notify kernel of partition table changes
111+
debug!("🔄 Syncing partition table changes");
112+
sync_gpt_partitions(&device.path)?;
17113

18-
// discover all loop devices
114+
// Get list of all loopback devices
115+
info!("🔍 Discovering block devices");
19116
let loop_devices = BlockDevice::discover()?
20117
.into_iter()
21118
.filter_map(|device| {
@@ -27,26 +124,29 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
27124
})
28125
.collect::<Vec<_>>();
29126

30-
// print loop devices
127+
// Display information about discovered devices
128+
info!("📋 Device information:");
31129
for loop_device in loop_devices {
32130
if let Some(file) = loop_device.file_path() {
33131
if let Some(disk) = loop_device.disk() {
34-
println!(
35-
"Loopback device: {} (backing file: {})",
132+
info!(
133+
"💾 Loopback device: {} (backing file: {})",
36134
loop_device.name(),
37135
file.display()
38136
);
39-
println!("└─Disk: {} ({})", disk.name(), disk.model().unwrap_or("Unknown"));
137+
info!(" └─Disk: {} ({})", disk.name(), disk.model().unwrap_or("Unknown"));
40138
for partition in disk.partitions() {
41-
println!(" ├─{} {partition}", partition.name);
139+
info!(" ├─{} {partition}", partition.name);
42140
}
43141
}
44142
}
45143
}
46144

47-
// detach loopback, remove img
145+
// Clean up resources
146+
debug!("🧹 Cleaning up resources");
48147
device.detach()?;
49-
fs::remove_file("hello.world")?;
148+
//fs::remove_file("hello.world")?;
50149

150+
info!("✨ Demo completed successfully");
51151
Ok(())
52152
}

0 commit comments

Comments
 (0)