From f6c3be42e79bd9abf49db6b37c08b54bcaf6b2e7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 22:17:58 +0100 Subject: [PATCH 1/3] storage: Vendor partitionlib to make it easier to change --- Cargo.lock | 1 - storage/driver-block/Cargo.toml | 2 +- storage/nvmed/Cargo.toml | 2 +- storage/partitionlib/Cargo.toml | 11 ++ storage/partitionlib/resources/disk.img | Bin 0 -> 524288 bytes storage/partitionlib/resources/disk_mbr.img | Bin 0 -> 2048 bytes storage/partitionlib/src/lib.rs | 7 ++ storage/partitionlib/src/mbr.rs | 77 +++++++++++++ storage/partitionlib/src/partition.rs | 115 ++++++++++++++++++++ storage/partitionlib/tests/test.rs | 54 +++++++++ storage/virtio-blkd/Cargo.toml | 2 +- storage/virtio-blkd/src/scheme.rs | 3 + 12 files changed, 270 insertions(+), 4 deletions(-) create mode 100644 storage/partitionlib/Cargo.toml create mode 100644 storage/partitionlib/resources/disk.img create mode 100644 storage/partitionlib/resources/disk_mbr.img create mode 100644 storage/partitionlib/src/lib.rs create mode 100644 storage/partitionlib/src/mbr.rs create mode 100644 storage/partitionlib/src/partition.rs create mode 100644 storage/partitionlib/tests/test.rs diff --git a/Cargo.lock b/Cargo.lock index e101de9edb..0bc2322768 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -937,7 +937,6 @@ dependencies = [ [[package]] name = "partitionlib" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/partitionlib.git#9e48718a0553a4d0d4070994053e1c402bb33b91" dependencies = [ "gpt", "scroll", diff --git a/storage/driver-block/Cargo.toml b/storage/driver-block/Cargo.toml index f876f19832..278520adca 100644 --- a/storage/driver-block/Cargo.toml +++ b/storage/driver-block/Cargo.toml @@ -4,6 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] -partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" } +partitionlib = { path = "../partitionlib" } redox_syscall = "0.5" diff --git a/storage/nvmed/Cargo.toml b/storage/nvmed/Cargo.toml index 1a00ca727a..04cf4bb27c 100644 --- a/storage/nvmed/Cargo.toml +++ b/storage/nvmed/Cargo.toml @@ -13,7 +13,7 @@ redox-daemon = "0.1" redox_syscall = { version = "0.5", features = ["std"] } redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" } redox_event = "0.4" -partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" } +partitionlib = { path = "../partitionlib" } smallvec = "1" common = { path = "../../common" } diff --git a/storage/partitionlib/Cargo.toml b/storage/partitionlib/Cargo.toml new file mode 100644 index 0000000000..27df61ce16 --- /dev/null +++ b/storage/partitionlib/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "partitionlib" +version = "0.1.0" +authors = ["Deepak Sirone "] +edition = "2018" +license = "MIT" + +[dependencies] +gpt = { version = "3.0.1" } +scroll = { version = "0.10", features = ["derive"] } +uuid = { version = "1.0", features = ["v4"] } diff --git a/storage/partitionlib/resources/disk.img b/storage/partitionlib/resources/disk.img new file mode 100644 index 0000000000000000000000000000000000000000..76913628c28ec5cbf5beaad39c4f62c41d87ca4a GIT binary patch literal 524288 zcmeI)F-yZh7zW_0{t*%BAE>wqRjS}7QWq-}#8Snt*kTMLR#PL)o&xw`16 zgE$qOgbu;h1k=H8I*7va!SQj)@#gNyoP?nMv%pAr?e+Va_z3;c@1JA&Vs3t6Y;k6( z7(ynj#sQPZ6AwvFl9<#Wb^LQ09@D23uiv^`E9Kd<+~MVOX?J@hy}uXtWOS#agSe?b zE^t!6>%6pch5eh2)>ZcC_B^Vz?rWR*({`!ZSby&gzxTm$*1}Gx4kkJQ0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF z5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs z0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZ zfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&U zAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C7 z2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N z0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+ z009C72oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk1PBly zK!5-N0t5&UAV7csfnO3hso!;8+PT91%|`1gdvtpqRa*D8&HQP*)NHK3_r}wGJdS?d z&|26D)vuS#2oNAZfB*pk1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+009C72oNAZfB*pk z1PBlyK!5-N0t5&UAV7cs0RjXF5FkK+0D&J0%*`*1EzT?zL&${HI3t?sTqIHb^n3qI onmha-fa3LAcWb3QdzL%Ad@k*7Kc(yU;`PbsPDclEQ-56G1ClsdMgRZ+ literal 0 HcmV?d00001 diff --git a/storage/partitionlib/resources/disk_mbr.img b/storage/partitionlib/resources/disk_mbr.img new file mode 100644 index 0000000000000000000000000000000000000000..429d41ca6b83c1e05578b40e84ac25758659273b GIT binary patch literal 2048 zcmeyhgF&G0!XAbVI~W-HZuA}ay^o=0KLguN2ByzTUMaFMFznmMZoyK@-F!@-@!vo8 z($BBOwlHmA+|5w4siCWcvD=5~tne#_8U}{f{}@IA{X#&#!TUSNHYSE<1{MZJAd8s{ Z%R^U@p=nghXb6mkz-S1JhQKfg0RT6oBp(0( literal 0 HcmV?d00001 diff --git a/storage/partitionlib/src/lib.rs b/storage/partitionlib/src/lib.rs new file mode 100644 index 0000000000..1b0b71b4e5 --- /dev/null +++ b/storage/partitionlib/src/lib.rs @@ -0,0 +1,7 @@ +extern crate gpt; +extern crate uuid; + +pub type Result = std::io::Result; +mod mbr; +pub mod partition; +pub use self::partition::*; diff --git a/storage/partitionlib/src/mbr.rs b/storage/partitionlib/src/mbr.rs new file mode 100644 index 0000000000..cf129ce356 --- /dev/null +++ b/storage/partitionlib/src/mbr.rs @@ -0,0 +1,77 @@ +use scroll::{Pread, Pwrite}; +use std::io; +use std::io::prelude::*; + +#[derive(Clone, Copy, Debug, Pread, Pwrite)] +pub struct Entry { + pub drive_attrs: u8, + pub start_head: u8, + pub start_cs: u16, + pub sys_id: u8, + pub end_head: u8, + pub end_cs: u16, + pub rel_sector: u32, + pub len: u32, +} + +#[derive(Pread, Pwrite)] +pub struct Header { + pub bootstrap: [u8; 446], + pub first_entry: Entry, + pub second_entry: Entry, + pub third_entry: Entry, + pub fourth_entry: Entry, + pub last_signature: u16, // 0xAA55 +} + +#[derive(Debug)] +pub enum Error { + IoError(io::Error), + ParsingError(scroll::Error), +} + +impl From for Error { + fn from(err: io::Error) -> Self { + Self::IoError(err) + } +} +impl From for Error { + fn from(err: scroll::Error) -> Self { + Self::ParsingError(err) + } +} + +pub fn read_header(device: &mut D) -> Result { + device.seek(io::SeekFrom::Start(0))?; + + let mut bytes = [0u8; 512]; + device.read_exact(&mut bytes)?; + + let header: Header = bytes.pread_with(0, scroll::LE)?; + + if header.last_signature != 0xAA55 { + return Err(scroll::Error::BadInput { + size: 2, + msg: "no 0xAA55 signature", + } + .into()); + } + + Ok(header) +} + +impl Header { + pub fn partitions(&self) -> [Entry; 4] { + [ + self.first_entry, + self.second_entry, + self.third_entry, + self.fourth_entry, + ] + } +} +impl Entry { + pub fn is_valid(&self) -> bool { + (self.drive_attrs == 0 || self.drive_attrs == 0x80) && self.len != 0 + } +} diff --git a/storage/partitionlib/src/partition.rs b/storage/partitionlib/src/partition.rs new file mode 100644 index 0000000000..030f292852 --- /dev/null +++ b/storage/partitionlib/src/partition.rs @@ -0,0 +1,115 @@ +use super::Result; +pub use gpt::disk::LogicalBlockSize; +use std::fs::File; +use std::io::prelude::*; +use std::path::Path; +use uuid::Uuid; + +/// A union of the MBR and GPT partition entry +#[derive(Clone, Debug, Eq, Hash, PartialEq)] +pub struct Partition { + /// The starting logical block number + pub start_lba: u64, + /// The size of the partition in sectors + pub size: u64, + pub flags: Option, + pub name: Option, + pub uuid: Option, +} + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub enum PartitionTableKind { + Mbr, + Gpt, +} +impl Default for PartitionTableKind { + fn default() -> Self { + Self::Gpt + } +} +impl PartitionTableKind { + pub fn is_mbr(self) -> bool { + self == Self::Mbr + } + pub fn is_gpt(self) -> bool { + self == Self::Gpt + } +} + +#[derive(Clone, Debug, Eq, PartialEq, Hash)] +pub struct PartitionTable { + pub partitions: Vec, + pub kind: PartitionTableKind, +} + +pub fn get_partitions_from_file>( + path: P, + sector_size: LogicalBlockSize, +) -> Result> { + let mut file = File::open(path)?; + get_partitions(&mut file, sector_size) +} +fn get_gpt_partitions( + device: &mut D, + sector_size: LogicalBlockSize, +) -> Result { + let header = match gpt::header::read_header_from_arbitrary_device(device, sector_size) { + Ok(res) => res, + Err(err) => return Err(err), + }; + Ok(PartitionTable { + partitions: gpt::partition::file_read_partitions(device, &header, sector_size).map( + |btree| { + btree + .into_iter() + .map(|(_, part)| Partition { + flags: Some(part.flags), + size: part.last_lba - part.first_lba + 1, + name: Some(part.name.clone()), + uuid: Some(part.part_guid), + start_lba: part.first_lba, + }) + .collect() + }, + )?, + kind: PartitionTableKind::Gpt, + }) +} +fn get_mbr_partitions(device: &mut D) -> Result> { + let header = match crate::mbr::read_header(device) { + Ok(h) => h, + Err(crate::mbr::Error::ParsingError(_)) => return Ok(None), + Err(crate::mbr::Error::IoError(ioerr)) => return Err(ioerr), + }; + Ok(Some(PartitionTable { + kind: PartitionTableKind::Mbr, + partitions: header + .partitions() + .iter() + .copied() + .filter(crate::mbr::Entry::is_valid) + .map(|partition: crate::mbr::Entry| Partition { + name: None, + uuid: None, // TODO: Some kind of one-way conversion should be possible + flags: None, // TODO + size: partition.len.into(), + start_lba: partition.rel_sector.into(), + }) + .collect(), + })) +} +pub fn get_partitions( + device: &mut D, + sector_size: LogicalBlockSize, +) -> Result> { + get_gpt_partitions(device, sector_size) + .map(Some) + .or_else(|_| get_mbr_partitions(device)) +} + +impl Partition { + pub fn to_offset(&self, sector_size: LogicalBlockSize) -> u64 { + let blksize: u64 = sector_size.into(); + self.start_lba * blksize + } +} diff --git a/storage/partitionlib/tests/test.rs b/storage/partitionlib/tests/test.rs new file mode 100644 index 0000000000..a9254c859b --- /dev/null +++ b/storage/partitionlib/tests/test.rs @@ -0,0 +1,54 @@ +extern crate partitionlib; + +use partitionlib::{get_partitions_from_file, LogicalBlockSize, Partition}; + +#[test] +fn part_is_gpt() { + assert!(dbg!( + get_partitions_from_file("./resources/disk.img", LogicalBlockSize::Lb512) + .unwrap() + .unwrap() + ) + .kind + .is_gpt()); +} + +#[test] +fn part_is_mbr() { + assert!( + get_partitions_from_file("./resources/disk_mbr.img", LogicalBlockSize::Lb512) + .unwrap() + .unwrap() + .kind + .is_mbr() + ); +} + +// NOTE: The following tests rely on outside resource files being correct. +#[test] +fn gpt() { + let table = get_partitions_from_file("./resources/disk.img", LogicalBlockSize::Lb512).unwrap().unwrap(); + assert_eq!(&table.partitions, &[ + Partition { + flags: Some(0), + name: Some("bug".to_owned()), + uuid: Some(uuid::Uuid::parse_str("b665fba9-74d5-4069-a6b9-5ba3a164fdfe").unwrap()), // Microsoft basic data + size: 957, + start_lba: 34, + } + ]); +} + +#[test] +fn mbr() { + let table = get_partitions_from_file("./resources/disk_mbr.img", LogicalBlockSize::Lb512).unwrap().unwrap(); + assert_eq!(&table.partitions, &[ + Partition { + flags: None, + name: None, + uuid: None, + size: 3, + start_lba: 1, + } + ]); +} diff --git a/storage/virtio-blkd/Cargo.toml b/storage/virtio-blkd/Cargo.toml index c9d09ad78d..de7aba04a1 100644 --- a/storage/virtio-blkd/Cargo.toml +++ b/storage/virtio-blkd/Cargo.toml @@ -15,7 +15,7 @@ spin = "*" redox-daemon = "0.1" redox_syscall = { version = "0.5", features = ["std"] } redox-scheme = { git = "https://gitlab.redox-os.org/redox-os/redox-scheme.git" } -partitionlib = { git = "https://gitlab.redox-os.org/redox-os/partitionlib.git" } +partitionlib = { path = "../partitionlib" } common = { path = "../../common" } driver-block = { path = "../driver-block" } diff --git a/storage/virtio-blkd/src/scheme.rs b/storage/virtio-blkd/src/scheme.rs index 217bf68f94..609f5f5059 100644 --- a/storage/virtio-blkd/src/scheme.rs +++ b/storage/virtio-blkd/src/scheme.rs @@ -191,6 +191,9 @@ impl<'a> DiskScheme<'a> { block_bytes: &mut [0u8; 4096], }; + //driver_block::DiskWrapper::new(disk) + + // FIXME use DiskWrapper instead let part_table = partitionlib::get_partitions(&mut shim, LogicalBlockSize::Lb512) .ok() .flatten(); From 398103e7103e732437764904106fc104e375b105 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 22:18:21 +0100 Subject: [PATCH 2/3] storage/partitionlib: Rustfmt --- storage/partitionlib/tests/test.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/storage/partitionlib/tests/test.rs b/storage/partitionlib/tests/test.rs index a9254c859b..c2a542a1c7 100644 --- a/storage/partitionlib/tests/test.rs +++ b/storage/partitionlib/tests/test.rs @@ -27,28 +27,34 @@ fn part_is_mbr() { // NOTE: The following tests rely on outside resource files being correct. #[test] fn gpt() { - let table = get_partitions_from_file("./resources/disk.img", LogicalBlockSize::Lb512).unwrap().unwrap(); - assert_eq!(&table.partitions, &[ - Partition { + let table = get_partitions_from_file("./resources/disk.img", LogicalBlockSize::Lb512) + .unwrap() + .unwrap(); + assert_eq!( + &table.partitions, + &[Partition { flags: Some(0), name: Some("bug".to_owned()), uuid: Some(uuid::Uuid::parse_str("b665fba9-74d5-4069-a6b9-5ba3a164fdfe").unwrap()), // Microsoft basic data size: 957, start_lba: 34, - } - ]); + }] + ); } #[test] fn mbr() { - let table = get_partitions_from_file("./resources/disk_mbr.img", LogicalBlockSize::Lb512).unwrap().unwrap(); - assert_eq!(&table.partitions, &[ - Partition { + let table = get_partitions_from_file("./resources/disk_mbr.img", LogicalBlockSize::Lb512) + .unwrap() + .unwrap(); + assert_eq!( + &table.partitions, + &[Partition { flags: None, name: None, uuid: None, size: 3, start_lba: 1, - } - ]); + }] + ); } From 9257cbbfa26a96e5ba22437eeb0c714c4bff10be Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 6 Mar 2025 22:25:24 +0100 Subject: [PATCH 3/3] storage/partitionlib: Couple of cleanups --- storage/partitionlib/Cargo.toml | 2 +- storage/partitionlib/src/lib.rs | 6 +-- storage/partitionlib/src/mbr.rs | 70 ++++++++++----------------- storage/partitionlib/src/partition.rs | 49 ++++--------------- storage/partitionlib/tests/test.rs | 41 +++++----------- 5 files changed, 49 insertions(+), 119 deletions(-) diff --git a/storage/partitionlib/Cargo.toml b/storage/partitionlib/Cargo.toml index 27df61ce16..8e5e3fad44 100644 --- a/storage/partitionlib/Cargo.toml +++ b/storage/partitionlib/Cargo.toml @@ -2,7 +2,7 @@ name = "partitionlib" version = "0.1.0" authors = ["Deepak Sirone "] -edition = "2018" +edition = "2021" license = "MIT" [dependencies] diff --git a/storage/partitionlib/src/lib.rs b/storage/partitionlib/src/lib.rs index 1b0b71b4e5..be369ce64e 100644 --- a/storage/partitionlib/src/lib.rs +++ b/storage/partitionlib/src/lib.rs @@ -1,7 +1,3 @@ -extern crate gpt; -extern crate uuid; - -pub type Result = std::io::Result; mod mbr; -pub mod partition; +mod partition; pub use self::partition::*; diff --git a/storage/partitionlib/src/mbr.rs b/storage/partitionlib/src/mbr.rs index cf129ce356..67ae5a6dad 100644 --- a/storage/partitionlib/src/mbr.rs +++ b/storage/partitionlib/src/mbr.rs @@ -1,77 +1,57 @@ use scroll::{Pread, Pwrite}; -use std::io; -use std::io::prelude::*; +use std::io::{self, Read, Seek}; #[derive(Clone, Copy, Debug, Pread, Pwrite)] -pub struct Entry { - pub drive_attrs: u8, - pub start_head: u8, - pub start_cs: u16, - pub sys_id: u8, - pub end_head: u8, - pub end_cs: u16, - pub rel_sector: u32, - pub len: u32, +pub(crate) struct Entry { + pub(crate) drive_attrs: u8, + pub(crate) start_head: u8, + pub(crate) start_cs: u16, + pub(crate) sys_id: u8, + pub(crate) end_head: u8, + pub(crate) end_cs: u16, + pub(crate) rel_sector: u32, + pub(crate) len: u32, } #[derive(Pread, Pwrite)] -pub struct Header { - pub bootstrap: [u8; 446], - pub first_entry: Entry, - pub second_entry: Entry, - pub third_entry: Entry, - pub fourth_entry: Entry, - pub last_signature: u16, // 0xAA55 +pub(crate) struct Header { + pub(crate) bootstrap: [u8; 446], + pub(crate) first_entry: Entry, + pub(crate) second_entry: Entry, + pub(crate) third_entry: Entry, + pub(crate) fourth_entry: Entry, + pub(crate) last_signature: u16, // 0xAA55 } -#[derive(Debug)] -pub enum Error { - IoError(io::Error), - ParsingError(scroll::Error), -} - -impl From for Error { - fn from(err: io::Error) -> Self { - Self::IoError(err) - } -} -impl From for Error { - fn from(err: scroll::Error) -> Self { - Self::ParsingError(err) - } -} - -pub fn read_header(device: &mut D) -> Result { +pub(crate) fn read_header(device: &mut D) -> io::Result> { device.seek(io::SeekFrom::Start(0))?; let mut bytes = [0u8; 512]; device.read_exact(&mut bytes)?; - let header: Header = bytes.pread_with(0, scroll::LE)?; + let header: Header = bytes.pread_with(0, scroll::LE).unwrap(); if header.last_signature != 0xAA55 { - return Err(scroll::Error::BadInput { - size: 2, - msg: "no 0xAA55 signature", - } - .into()); + return Ok(None); } - Ok(header) + Ok(Some(header)) } impl Header { - pub fn partitions(&self) -> [Entry; 4] { + pub(crate) fn partitions(&self) -> impl Iterator { [ self.first_entry, self.second_entry, self.third_entry, self.fourth_entry, ] + .into_iter() + .filter(Entry::is_valid) } } impl Entry { - pub fn is_valid(&self) -> bool { + fn is_valid(&self) -> bool { (self.drive_attrs == 0 || self.drive_attrs == 0x80) && self.len != 0 } } diff --git a/storage/partitionlib/src/partition.rs b/storage/partitionlib/src/partition.rs index 030f292852..949171511b 100644 --- a/storage/partitionlib/src/partition.rs +++ b/storage/partitionlib/src/partition.rs @@ -1,8 +1,5 @@ -use super::Result; pub use gpt::disk::LogicalBlockSize; -use std::fs::File; -use std::io::prelude::*; -use std::path::Path; +use std::io::{self, Read, Seek}; use uuid::Uuid; /// A union of the MBR and GPT partition entry @@ -17,46 +14,23 @@ pub struct Partition { pub uuid: Option, } -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum PartitionTableKind { Mbr, Gpt, } -impl Default for PartitionTableKind { - fn default() -> Self { - Self::Gpt - } -} -impl PartitionTableKind { - pub fn is_mbr(self) -> bool { - self == Self::Mbr - } - pub fn is_gpt(self) -> bool { - self == Self::Gpt - } -} -#[derive(Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Clone, Debug, Eq, PartialEq)] pub struct PartitionTable { pub partitions: Vec, pub kind: PartitionTableKind, } -pub fn get_partitions_from_file>( - path: P, - sector_size: LogicalBlockSize, -) -> Result> { - let mut file = File::open(path)?; - get_partitions(&mut file, sector_size) -} fn get_gpt_partitions( device: &mut D, sector_size: LogicalBlockSize, -) -> Result { - let header = match gpt::header::read_header_from_arbitrary_device(device, sector_size) { - Ok(res) => res, - Err(err) => return Err(err), - }; +) -> io::Result { + let header = gpt::header::read_header_from_arbitrary_device(device, sector_size)?; Ok(PartitionTable { partitions: gpt::partition::file_read_partitions(device, &header, sector_size).map( |btree| { @@ -75,19 +49,14 @@ fn get_gpt_partitions( kind: PartitionTableKind::Gpt, }) } -fn get_mbr_partitions(device: &mut D) -> Result> { - let header = match crate::mbr::read_header(device) { - Ok(h) => h, - Err(crate::mbr::Error::ParsingError(_)) => return Ok(None), - Err(crate::mbr::Error::IoError(ioerr)) => return Err(ioerr), +fn get_mbr_partitions(device: &mut D) -> io::Result> { + let Some(header) = crate::mbr::read_header(device)? else { + return Ok(None); }; Ok(Some(PartitionTable { kind: PartitionTableKind::Mbr, partitions: header .partitions() - .iter() - .copied() - .filter(crate::mbr::Entry::is_valid) .map(|partition: crate::mbr::Entry| Partition { name: None, uuid: None, // TODO: Some kind of one-way conversion should be possible @@ -101,7 +70,7 @@ fn get_mbr_partitions(device: &mut D) -> Result( device: &mut D, sector_size: LogicalBlockSize, -) -> Result> { +) -> io::Result> { get_gpt_partitions(device, sector_size) .map(Some) .or_else(|_| get_mbr_partitions(device)) diff --git a/storage/partitionlib/tests/test.rs b/storage/partitionlib/tests/test.rs index c2a542a1c7..c4ef93220e 100644 --- a/storage/partitionlib/tests/test.rs +++ b/storage/partitionlib/tests/test.rs @@ -1,35 +1,21 @@ -extern crate partitionlib; +use std::fs::File; -use partitionlib::{get_partitions_from_file, LogicalBlockSize, Partition}; +use partitionlib::{ + get_partitions, LogicalBlockSize, Partition, PartitionTable, PartitionTableKind, +}; -#[test] -fn part_is_gpt() { - assert!(dbg!( - get_partitions_from_file("./resources/disk.img", LogicalBlockSize::Lb512) - .unwrap() - .unwrap() - ) - .kind - .is_gpt()); -} - -#[test] -fn part_is_mbr() { - assert!( - get_partitions_from_file("./resources/disk_mbr.img", LogicalBlockSize::Lb512) - .unwrap() - .unwrap() - .kind - .is_mbr() - ); +fn get_partitions_from_file(path: &str) -> PartitionTable { + let mut file = File::open(path).unwrap(); + get_partitions(&mut file, LogicalBlockSize::Lb512) + .unwrap() + .unwrap() } // NOTE: The following tests rely on outside resource files being correct. #[test] fn gpt() { - let table = get_partitions_from_file("./resources/disk.img", LogicalBlockSize::Lb512) - .unwrap() - .unwrap(); + let table = get_partitions_from_file("./resources/disk.img"); + assert_eq!(table.kind, PartitionTableKind::Gpt); assert_eq!( &table.partitions, &[Partition { @@ -44,9 +30,8 @@ fn gpt() { #[test] fn mbr() { - let table = get_partitions_from_file("./resources/disk_mbr.img", LogicalBlockSize::Lb512) - .unwrap() - .unwrap(); + let table = get_partitions_from_file("./resources/disk_mbr.img"); + assert_eq!(table.kind, PartitionTableKind::Mbr); assert_eq!( &table.partitions, &[Partition {