storage: Vendor partitionlib to make it easier to change
This commit is contained in:
Generated
-1
@@ -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",
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "partitionlib"
|
||||
version = "0.1.0"
|
||||
authors = ["Deepak Sirone <deepaksirone94@gmail.com>"]
|
||||
edition = "2018"
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
gpt = { version = "3.0.1" }
|
||||
scroll = { version = "0.10", features = ["derive"] }
|
||||
uuid = { version = "1.0", features = ["v4"] }
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
extern crate gpt;
|
||||
extern crate uuid;
|
||||
|
||||
pub type Result<T> = std::io::Result<T>;
|
||||
mod mbr;
|
||||
pub mod partition;
|
||||
pub use self::partition::*;
|
||||
@@ -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<io::Error> for Error {
|
||||
fn from(err: io::Error) -> Self {
|
||||
Self::IoError(err)
|
||||
}
|
||||
}
|
||||
impl From<scroll::Error> for Error {
|
||||
fn from(err: scroll::Error) -> Self {
|
||||
Self::ParsingError(err)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read_header<D: Read + Seek>(device: &mut D) -> Result<Header, Error> {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -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<u64>,
|
||||
pub name: Option<String>,
|
||||
pub uuid: Option<Uuid>,
|
||||
}
|
||||
|
||||
#[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<Partition>,
|
||||
pub kind: PartitionTableKind,
|
||||
}
|
||||
|
||||
pub fn get_partitions_from_file<P: AsRef<Path>>(
|
||||
path: P,
|
||||
sector_size: LogicalBlockSize,
|
||||
) -> Result<Option<PartitionTable>> {
|
||||
let mut file = File::open(path)?;
|
||||
get_partitions(&mut file, sector_size)
|
||||
}
|
||||
fn get_gpt_partitions<D: Read + Seek>(
|
||||
device: &mut D,
|
||||
sector_size: LogicalBlockSize,
|
||||
) -> Result<PartitionTable> {
|
||||
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<D: Read + Seek>(device: &mut D) -> Result<Option<PartitionTable>> {
|
||||
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<D: Read + Seek>(
|
||||
device: &mut D,
|
||||
sector_size: LogicalBlockSize,
|
||||
) -> Result<Option<PartitionTable>> {
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
}
|
||||
]);
|
||||
}
|
||||
@@ -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" }
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user