Struct Disk

Source
pub struct Disk<Io: BlockIo> { /* private fields */ }
Expand description

Read and write GPT disk data.

The disk is accessed via an object implementing the BlockIo trait, so all reads and writes are on block boundaries. Writes are not guaranteed to be completed until flush is called. This happens automatically when the Disk is dropped, but if an error occurs at that point it will be silently ignored so it is recommended to call flush directly before dropping the disk.

Many of the methods on Disk take a block_buf argument, which is a mutable byte buffer with a length of at least one block. (The read_gpt_partition_entry_array and write_gpt_partition_entry_array methods take a larger storage argument that is multiple blocks in size.) These buffer arguments allow Disk to avoid doing any internal memory allocation.

§Partition entry arrays

Partition entry arrays can be read in two ways: one block at a time with gpt_partition_entry_array_iter, or all at once with read_gpt_partition_entry_array. The former allows a smaller amount of memory usage bounded to the block size, while the latter may be more efficient since all the blocks can be read at once.

Writing the array can currently only be done all at once via write_gpt_partition_entry_array; a block-at-a-time method may be added in the future.

Implementations§

Source§

impl<Io: BlockIo> Disk<Io>

Source

pub fn new(io: Io) -> Result<Self, DiskError<Io::Error>>

Create a Disk.

Examples found in repository?
examples/reader.rs (line 32)
23fn main() -> Result<(), Box<dyn error::Error>> {
24    let disk_path = env::args().nth(1).expect("one argument is required");
25    println!("opening {} for reading", disk_path);
26
27    let file = fs::File::open(disk_path)?;
28
29    let mut block_buf = vec![0u8; 512];
30
31    let block_io = BlockIoAdapter::new(file, BlockSize::BS_512);
32    let mut disk = Disk::new(block_io)?;
33
34    let primary_header = disk.read_primary_gpt_header(&mut block_buf)?;
35    println!("{}", primary_header);
36    assert!(primary_header.is_signature_valid());
37
38    let layout = primary_header.get_partition_entry_array_layout()?;
39    for entry in disk.gpt_partition_entry_array_iter(layout, &mut block_buf)? {
40        let entry = entry?;
41        if entry.is_used() {
42            println!("{}", entry);
43        }
44    }
45
46    Ok(())
47}
Source

pub fn read_primary_gpt_header( &mut self, block_buf: &mut [u8], ) -> Result<GptHeader, DiskError<Io::Error>>

Read the primary GPT header from the second block. No validation of the header is performed.

Examples found in repository?
examples/reader.rs (line 34)
23fn main() -> Result<(), Box<dyn error::Error>> {
24    let disk_path = env::args().nth(1).expect("one argument is required");
25    println!("opening {} for reading", disk_path);
26
27    let file = fs::File::open(disk_path)?;
28
29    let mut block_buf = vec![0u8; 512];
30
31    let block_io = BlockIoAdapter::new(file, BlockSize::BS_512);
32    let mut disk = Disk::new(block_io)?;
33
34    let primary_header = disk.read_primary_gpt_header(&mut block_buf)?;
35    println!("{}", primary_header);
36    assert!(primary_header.is_signature_valid());
37
38    let layout = primary_header.get_partition_entry_array_layout()?;
39    for entry in disk.gpt_partition_entry_array_iter(layout, &mut block_buf)? {
40        let entry = entry?;
41        if entry.is_used() {
42            println!("{}", entry);
43        }
44    }
45
46    Ok(())
47}
Source

pub fn read_secondary_gpt_header( &mut self, block_buf: &mut [u8], ) -> Result<GptHeader, DiskError<Io::Error>>

Read the secondary GPT header from the last block. No validation of the header is performed.

block_buf is a mutable byte buffer with a length of at least one block.

Source

pub fn read_gpt_header( &mut self, lba: Lba, block_buf: &mut [u8], ) -> Result<GptHeader, DiskError<Io::Error>>

Read a GPT header at the given Lba. No validation of the header is performed.

block_buf is a mutable byte buffer with a length of at least one block.

Source

pub fn read_gpt_partition_entry_array<'buf>( &mut self, layout: GptPartitionEntryArrayLayout, storage: &'buf mut [u8], ) -> Result<GptPartitionEntryArray<'buf>, DiskError<Io::Error>>

Read the entire partition entry array. The storage buffer must be at least layout.num_bytes_rounded_to_block in size.

Source

pub fn write_gpt_partition_entry_array( &mut self, entry_array: &GptPartitionEntryArray<'_>, ) -> Result<(), DiskError<Io::Error>>

Write an entire GptPartitionEntryArray to disk.

Source

pub fn gpt_partition_entry_array_iter<'disk, 'buf>( &'disk mut self, layout: GptPartitionEntryArrayLayout, block_buf: &'buf mut [u8], ) -> Result<impl Iterator<Item = Result<GptPartitionEntry, DiskError<Io::Error>>> + Captures<'disk, 'buf>, DiskError<Io::Error>>

Get an iterator over partition entries. The layout parameter indicates where to read the entries from; see GptPartitionEntryArrayLayout for more.

block_buf is a mutable byte buffer with a length of at least one block.

Examples found in repository?
examples/reader.rs (line 39)
23fn main() -> Result<(), Box<dyn error::Error>> {
24    let disk_path = env::args().nth(1).expect("one argument is required");
25    println!("opening {} for reading", disk_path);
26
27    let file = fs::File::open(disk_path)?;
28
29    let mut block_buf = vec![0u8; 512];
30
31    let block_io = BlockIoAdapter::new(file, BlockSize::BS_512);
32    let mut disk = Disk::new(block_io)?;
33
34    let primary_header = disk.read_primary_gpt_header(&mut block_buf)?;
35    println!("{}", primary_header);
36    assert!(primary_header.is_signature_valid());
37
38    let layout = primary_header.get_partition_entry_array_layout()?;
39    for entry in disk.gpt_partition_entry_array_iter(layout, &mut block_buf)? {
40        let entry = entry?;
41        if entry.is_used() {
42            println!("{}", entry);
43        }
44    }
45
46    Ok(())
47}
Source

pub fn write_protective_mbr( &mut self, block_buf: &mut [u8], ) -> Result<(), DiskError<Io::Error>>

Write a protective MBR to the first block. If the block size is bigger than the MBR, the rest of the block will be filled with zeroes.

block_buf is a mutable byte buffer with a length of at least one block.

Source

pub fn write_mbr( &mut self, mbr: &MasterBootRecord, block_buf: &mut [u8], ) -> Result<(), DiskError<Io::Error>>

Write an MBR to the first block. If the block size is bigger than the MBR, the rest of the block will be filled with zeroes.

block_buf is a mutable byte buffer with a length of at least one block.

Source

pub fn write_primary_gpt_header( &mut self, header: &GptHeader, block_buf: &mut [u8], ) -> Result<(), DiskError<Io::Error>>

Write the primary GPT header to the second block.

The header is written to the beginning of the block, and all remaining bytes in the block are set to zero (see Table 5-5 “GPT Header” in the UEFI Specification: “The rest of the block is reserved by UEFI and must be zero”).

block_buf is a mutable byte buffer with a length of at least one block.

Source

pub fn write_secondary_gpt_header( &mut self, header: &GptHeader, block_buf: &mut [u8], ) -> Result<(), DiskError<Io::Error>>

Write the secondary GPT header to the last block.

The header is written to the beginning of the block, and all remaining bytes in the block are set to zero (see Table 5-5 “GPT Header” in the UEFI Specification: “The rest of the block is reserved by UEFI and must be zero”).

block_buf is a mutable byte buffer with a length of at least one block.

Source

pub fn write_gpt_header( &mut self, lba: Lba, header: &GptHeader, block_buf: &mut [u8], ) -> Result<(), DiskError<Io::Error>>

Write a GptHeader to the specified Lba.

The header is written to the beginning of the block, and all remaining bytes in the block are set to zero (see Table 5-5 “GPT Header” in the UEFI Specification: “The rest of the block is reserved by UEFI and must be zero”).

block_buf is a mutable byte buffer with a length of at least one block.

Source

pub fn flush(&mut self) -> Result<(), DiskError<Io::Error>>

Flush any pending writes to the disk.

This is called automatically when the disk is dropped, but if an error occurs at that point it will be silently ignored. It is recommended to call this method directly before dropping the disk.

Trait Implementations§

Source§

impl<Io: BlockIo> Drop for Disk<Io>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

§

impl<Io> Freeze for Disk<Io>
where Io: Freeze,

§

impl<Io> RefUnwindSafe for Disk<Io>
where Io: RefUnwindSafe,

§

impl<Io> Send for Disk<Io>
where Io: Send,

§

impl<Io> Sync for Disk<Io>
where Io: Sync,

§

impl<Io> Unpin for Disk<Io>
where Io: Unpin,

§

impl<Io> UnwindSafe for Disk<Io>
where Io: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.