use icsneoc2::{Device, DiskFormatFlags, DiskLayout, OpenOptions};
use std::io::{self, BufRead, Write};
unsafe extern "C" fn format_progress(
sectors_formatted: u64,
total_sectors: u64,
user_data: *mut std::ffi::c_void,
) -> u8 {
let pct = if total_sectors > 0 {
100 * sectors_formatted / total_sectors
} else {
0
};
if !user_data.is_null() {
let device = unsafe { &*(user_data as *const Device) };
let name = device
.description()
.unwrap_or_else(|_| "unknown".to_string());
print!(
"\r [{name}] Progress: {} / {} sectors ({}%)",
sectors_formatted, total_sectors, pct
);
} else {
print!(
"\r Progress: {} / {} sectors ({}%)",
sectors_formatted, total_sectors, pct
);
}
let _ = io::stdout().flush();
0 }
fn main() -> anyhow::Result<()> {
println!("Opening first available device...");
let options = OpenOptions::NONE;
let device = Device::open_first(0, options)?;
let desc = device.description()?;
println!("\tOpened device: {desc}");
let supported = device.supports_disk_formatting()?;
if !supported {
println!("\terror: {desc} does not support disk formatting");
return Ok(());
}
let disk_count = device.disk_count()?;
println!("\tDisk count: {disk_count}");
print!("\tQuerying disk details... ");
let details = device.disk_details()?;
println!("OK");
let layout = details.layout()?;
let layout_name = match layout {
DiskLayout::Raid0 => "RAID0",
DiskLayout::Spanned => "Spanned",
_ => "Unknown",
};
println!("\t Layout : {layout_name}");
let detail_count = details.count()?;
let mut any_present = false;
for i in 0..detail_count {
let flags = details.flags(i)?;
println!("\t Disk [{i}]:");
println!(
"\t Present : {}",
if flags.contains(DiskFormatFlags::PRESENT) {
"yes"
} else {
"no"
}
);
println!(
"\t Initialized : {}",
if flags.contains(DiskFormatFlags::INITIALIZED) {
"yes"
} else {
"no"
}
);
println!(
"\t Formatted : {}",
if flags.contains(DiskFormatFlags::FORMATTED) {
"yes"
} else {
"no"
}
);
if flags.contains(DiskFormatFlags::PRESENT) {
let sz = details.size(i)?;
let mb = (sz.sectors * sz.bytes_per_sector) / (1024 * 1024);
println!(
"\t Size : {} MB ({} sectors x {} bytes)",
mb, sz.sectors, sz.bytes_per_sector
);
}
}
for i in 0..detail_count {
let flags = details.flags(i)?;
if flags.contains(DiskFormatFlags::PRESENT) {
details.set_flags(i, flags | DiskFormatFlags::FORMATTED)?;
any_present = true;
}
}
details.set_full_format(false)?;
if !any_present {
println!("\n\terror: no disks are present in the device");
return Ok(());
}
println!("\n\tThis will format the disk(s) in {desc}.");
print!("\tAll existing data will be lost. Continue? [y/N]: ");
io::stdout().flush().unwrap();
let mut input = String::new();
io::stdin().lock().read_line(&mut input).unwrap();
let input = input.trim();
if !input.eq_ignore_ascii_case("y") {
println!("\tAborted.");
return Ok(());
}
println!("\n\tStarting format...");
unsafe {
let user_data = &device as *const Device as *mut std::ffi::c_void;
device.format_disk(&details, Some(format_progress), user_data)?;
}
println!("\n\tFormat complete!");
print!("\n\tVerifying disk state after format... ");
let post_details = device.disk_details()?;
println!("OK");
let post_count = post_details.count()?;
for i in 0..post_count {
let flags = post_details.flags(i)?;
println!(
"\t Disk [{i}] formatted: {}",
if flags.contains(DiskFormatFlags::FORMATTED) {
"yes"
} else {
"no"
}
);
}
println!("\tClosing device: {desc}...");
Ok(())
}