use crate::error::{Error, Result};
use crate::gpt;
use crate::mbr;
use crate::BlockRead;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TableKind {
Gpt,
Mbr,
}
#[derive(Debug, Clone)]
pub struct Partition {
pub start: u64,
pub length: u64,
pub kind: PartitionKind,
pub label: Option<String>,
pub uuid: Option<[u8; 16]>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PartitionKind {
Gpt { type_guid: [u8; 16] },
Mbr { type_byte: u8 },
Whole,
}
pub fn probe(dev: &dyn BlockRead) -> Result<(TableKind, Vec<Partition>)> {
let mut lba0 = [0u8; 512];
let mut lba1 = [0u8; 512];
dev.read_at(0, &mut lba0)?;
if dev.size_bytes() >= 1024 {
dev.read_at(512, &mut lba1)?;
}
let has_mbr_sig = lba0[510] == 0x55 && lba0[511] == 0xAA;
let gpt_sig = &lba1[0..8];
let has_gpt_sig = gpt_sig == gpt::SIGNATURE;
if has_gpt_sig {
let parts = gpt::parse(dev, &lba1)?;
return Ok((TableKind::Gpt, parts));
}
if has_mbr_sig {
if mbr::is_protective(&lba0) {
return Err(Error::GptCorrupt(
"protective MBR present but no GPT signature",
));
}
let parts = mbr::parse(&lba0)?;
return Ok((TableKind::Mbr, parts));
}
Err(Error::NoPartitionTable)
}