storage_list/
lib.rs

1use std::ffi::OsString;
2use std::fs::read_dir;
3use std::fs::read_to_string;
4use std::io::Error as IoError;
5
6#[derive(Debug, Clone)]
7pub struct StorageDevice {
8	pub name: String,
9	pub capacity: usize,
10	pub partitions: Vec<Partition>,
11	pub read_only: bool,
12}
13
14#[derive(Debug, Clone)]
15pub struct Partition {
16	pub name: String,
17	pub capacity: usize,
18	pub read_only: bool,
19}
20
21fn read_prop(base: &str, prop: &str) -> Option<String> {
22	let value = read_to_string(format!("{}/{}", base, prop)).ok()?;
23	Some(String::from(&value[..value.len() - 1]))
24}
25
26fn read_partition(device: &str, entry: OsString, sector_size: usize) -> Option<Partition> {
27	let name = entry.into_string().ok()?;
28	let path = format!("/sys/block/{}/{}", device, name);
29	let sectors = read_prop(&path, "size")?.parse::<usize>().ok()?;
30	let read_only = read_prop(&path, "ro")? == "1";
31	Some(Partition {
32		name,
33		capacity: sectors * sector_size,
34		read_only,
35	})
36}
37
38fn read_device(entry: OsString) -> Option<StorageDevice> {
39	let name = entry.into_string().ok()?;
40	let path = format!("/sys/block/{}", name);
41	let sectors = read_prop(&path, "size")?.parse::<usize>().ok()?;
42	let sector_size = read_prop(&path, "queue/hw_sector_size")?.parse().ok()?;
43	let read_only = read_prop(&path, "ro")? == "1";
44	let mut partitions = Vec::new();
45	for entry in read_dir(&path).ok()? {
46		if let Some(partition) = read_partition(&name, entry.ok()?.file_name(), sector_size) {
47			partitions.push(partition);
48		}
49	}
50	Some(StorageDevice {
51		name,
52		capacity: sectors * sector_size,
53		partitions,
54		read_only,
55	})
56}
57
58pub fn list_partitions() -> Result<Vec<StorageDevice>, IoError> {
59	let mut devices = Vec::new();
60	for entry in read_dir("/sys/block")? {
61		if let Some(device) = read_device(entry?.file_name()) {
62			devices.push(device);
63		}
64	}
65	Ok(devices)
66}