Struct GPT

Source
pub struct GPT {
    pub sector_size: u64,
    pub header: GPTHeader,
    pub align: u64,
    /* private fields */
}
Expand description

A type representing a GUID partition table including its partitions, the sector size of the disk and the alignment of the partitions to the sectors.

§Examples

Read an existing GPT on a reader and list its partitions:

let mut f = std::fs::File::open("tests/fixtures/disk1.img")
    .expect("could not open disk");
let gpt = gptman::GPT::find_from(&mut f)
    .expect("could not find GPT");

println!("Disk GUID: {:?}", gpt.header.disk_guid);

for (i, p) in gpt.iter() {
    if p.is_used() {
        println!("Partition #{}: type = {:?}, size = {} bytes, starting lba = {}",
            i,
            p.partition_type_guid,
            p.size().unwrap() * gpt.sector_size,
            p.starting_lba);
    }
}

Fields§

§sector_size: u64

Sector size of the disk.

You should not change this, otherwise the starting locations of your partitions will be different in bytes.

§header: GPTHeader

GPT partition header (disk GUID, first/last usable LBA, etc…)

§align: u64

Partitions alignment (in sectors)

This field change the behavior of the methods get_maximum_partition_size(), find_free_sectors(), find_first_place(), find_last_place() and find_optimal_place() so they return only values aligned to the alignment.

§Panics

The value must be greater than 0, otherwise you will encounter divisions by zero.

Implementations§

Source§

impl GPT

Source

pub fn new_from<R>( reader: &mut R, sector_size: u64, disk_guid: [u8; 16], ) -> Result<GPT>
where R: Read + Seek,

Make a new GPT based on a reader. (This operation does not write anything to disk!)

§Examples

Basic usage:

let ss = 512;
let data = vec![0; 100 * ss as usize];
let mut cur = std::io::Cursor::new(data);
let gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16])
    .expect("could not make a partition table");
Source

pub fn read_from<R>(reader: &mut R, sector_size: u64) -> Result<GPT>
where R: Read + Seek + ?Sized,

Read the GPT on a reader. This function will try to read the backup header if the primary header could not be read.

§Implementation notes

The field last_usable_lba on the header is not updated to reflect the actual size of the disk. You must do this yourself by calling update_from.

§Examples

Basic usage:

let mut f = std::fs::File::open("tests/fixtures/disk1.img")
    .expect("could not open disk");
let gpt = gptman::GPT::read_from(&mut f, 512)
    .expect("could not read the partition table");
Source

pub fn find_from<R>(reader: &mut R) -> Result<GPT>
where R: Read + Seek + ?Sized,

Find the GPT on a reader. This function will try to read the GPT on a disk using a sector size of 512 but if it fails it will automatically try to read the GPT using a sector size of 4096.

§Examples

Basic usage:

let mut f_512 = std::fs::File::open("tests/fixtures/disk1.img")
    .expect("could not open disk");
let gpt_512 = gptman::GPT::find_from(&mut f_512)
    .expect("could not read the partition table");

let mut f_4096 = std::fs::File::open("tests/fixtures/disk2.img")
    .expect("could not open disk");
let gpt_4096 = gptman::GPT::find_from(&mut f_4096)
    .expect("could not read the partition table");
Source

pub fn write_into<W>(&mut self, writer: &mut W) -> Result<GPTHeader>
where W: Write + Seek + ?Sized,

Write the GPT to a writer. This function will seek automatically in the writer to write the primary header and the backup header at their proper location.

Returns the backup GPTHeader that has been wrote in case of success (or the primary GPTHeader if self was using a backup header).

Note that the checksums are re-calculated, thus updating the header.

§Errors

The partitions will be checked for consistency before being wrote to disk:

  • the partition GUIDs must be unique,
  • the partitions must have positive size,
  • the partitions must not overlap,
  • the partitions must fit within the disk.
§Examples

Basic usage:

let ss = 512;
let data = vec![0; 100 * ss as usize];
let mut cur = std::io::Cursor::new(data);
let mut gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16])
    .expect("could not make a partition table");

// actually write:
gpt.write_into(&mut cur)
    .expect("could not write GPT to disk");
Source

pub fn find_at_sector(&self, sector: u64) -> Option<u32>

Finds the partition where the given sector resides.

Source

pub fn find_free_sectors(&self) -> Vec<(u64, u64)>

Find free spots in the partition table.

This function will return a vector of tuple with on the left: the starting LBA of the free spot; and on the right: the size (in sectors) of the free spot.

This function will automatically align with the alignment defined in the GPT.

§Examples

Basic usage:

let ss = 512;
let data = vec![0; 100 * ss as usize];
let mut cur = std::io::Cursor::new(data);
let mut gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16])
    .expect("could not create partition table");

gpt[1] = gptman::GPTPartitionEntry {
    partition_type_guid: [0xff; 16],
    unique_partition_guid: [0xff; 16],
    starting_lba: gpt.header.first_usable_lba + 5,
    ending_lba: gpt.header.last_usable_lba - 5,
    attribute_bits: 0,
    partition_name: "A Robot Named Fight!".into(),
};

// NOTE: align to the sectors, so we can use every last one of them
// NOTE: this is only for the demonstration purpose, this is not recommended
gpt.align = 1;

assert_eq!(
    gpt.find_free_sectors(),
    vec![(gpt.header.first_usable_lba, 5), (gpt.header.last_usable_lba - 4, 5)]
);
Source

pub fn find_first_place(&self, size: u64) -> Option<u64>

Find the first place (most on the left) where you could start a new partition of the size given in parameter. This function will automatically align with the alignment defined in the GPT.

§Examples

Basic usage:

let ss = 512;
let data = vec![0; 100 * ss as usize];
let mut cur = std::io::Cursor::new(data);
let mut gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16])
    .expect("could not create partition table");

gpt[1] = gptman::GPTPartitionEntry {
    partition_type_guid: [0xff; 16],
    unique_partition_guid: [0xff; 16],
    starting_lba: gpt.header.first_usable_lba + 5,
    ending_lba: gpt.header.last_usable_lba - 5,
    attribute_bits: 0,
    partition_name: "A Robot Named Fight!".into(),
};

// NOTE: align to the sectors, so we can use every last one of them
// NOTE: this is only for the demonstration purpose, this is not recommended
gpt.align = 1;

assert_eq!(gpt.find_first_place(5), Some(gpt.header.first_usable_lba));
Source

pub fn find_last_place(&self, size: u64) -> Option<u64>

Find the last place (most on the right) where you could start a new partition of the size given in parameter.

This function will automatically align with the alignment defined in the GPT.

§Examples

Basic usage:

let ss = 512;
let data = vec![0; 100 * ss as usize];
let mut cur = std::io::Cursor::new(data);
let mut gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16])
    .expect("could not create partition table");

gpt[1] = gptman::GPTPartitionEntry {
    partition_type_guid: [0xff; 16],
    unique_partition_guid: [0xff; 16],
    starting_lba: gpt.header.first_usable_lba + 5,
    ending_lba: gpt.header.last_usable_lba - 5,
    attribute_bits: 0,
    partition_name: "A Robot Named Fight!".into(),
};

// NOTE: align to the sectors, so we can use every last one of them
// NOTE: this is only for the demonstration purpose, this is not recommended
gpt.align = 1;

assert_eq!(gpt.find_last_place(5), Some(gpt.header.last_usable_lba - 4));
Source

pub fn find_optimal_place(&self, size: u64) -> Option<u64>

Find the most optimal place (in the smallest free space) where you could start a new partition of the size given in parameter. This function will automatically align with the alignment defined in the GPT.

§Examples

Basic usage:

let ss = 512;
let data = vec![0; 100 * ss as usize];
let mut cur = std::io::Cursor::new(data);
let mut gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16])
    .expect("could not create partition table");

gpt[1] = gptman::GPTPartitionEntry {
    partition_type_guid: [0xff; 16],
    unique_partition_guid: [0xff; 16],
    starting_lba: gpt.header.first_usable_lba + 10,
    ending_lba: gpt.header.last_usable_lba - 5,
    attribute_bits: 0,
    partition_name: "A Robot Named Fight!".into(),
};

// NOTE: align to the sectors, so we can use every last one of them
// NOTE: this is only for the demonstration purpose, this is not recommended
gpt.align = 1;

// NOTE: the space as the end is more optimal because it will allow you to still be able to
//       insert a bigger partition later
assert_eq!(gpt.find_optimal_place(5), Some(gpt.header.last_usable_lba - 4));
Source

pub fn get_maximum_partition_size(&self) -> Result<u64>

Get the maximum size (in sectors) of a partition you could create in the GPT. This function will automatically align with the alignment defined in the GPT.

§Examples

Basic usage:

let ss = 512;
let data = vec![0; 100 * ss as usize];
let mut cur = std::io::Cursor::new(data);
let mut gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16])
    .expect("could not create partition table");

// NOTE: align to the sectors, so we can use every last one of them
// NOTE: this is only for the demonstration purpose, this is not recommended
gpt.align = 1;

assert_eq!(
    gpt.get_maximum_partition_size().unwrap_or(0),
    gpt.header.last_usable_lba + 1 - gpt.header.first_usable_lba
);
Source

pub fn get_partition_byte_range( &self, partition_number: u32, ) -> Result<RangeInclusive<u64>>

Get the range of bytes covered by a partition.

§Errors

This function will return an error if the partition number is invalid, or if the partition is unused, or if the partition’s ending_lba is less than its starting_lba.

§Examples
let ss = 512;
let data = vec![0; 100 * ss as usize];
let mut cur = std::io::Cursor::new(data);
let mut gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16])
    .expect("could not create partition table");
gpt[1] = gptman::GPTPartitionEntry {
    partition_type_guid: [0xff; 16],
    unique_partition_guid: [0xff; 16],
    starting_lba: 2048,
    ending_lba: 2048,
    attribute_bits: 0,
    partition_name: "A Robot Named Fight!".into(),
};

assert_eq!(gpt.get_partition_byte_range(1).unwrap(), 1048576..=1049087);
Source

pub fn sort(&mut self)

Sort the partition entries in the array by the starting LBA.

Source

pub fn remove(&mut self, i: u32) -> Result<()>

Remove a partition entry in the array.

This is the equivalent of: gpt[i] = gptman::GPTPartitionEntry::empty();

§Errors

This function will return an error if i is lesser or equal to 0 or greater than the number of partition entries (which can be obtained in the header).

Source

pub fn remove_at_sector(&mut self, sector: u64) -> Result<()>

Remove a partition entry in the array that resides at a given sector.

§Errors

It is an error to provide a sector which does not belong to a partition.

Source

pub fn iter(&self) -> impl Iterator<Item = (u32, &GPTPartitionEntry)>

Get an iterator over the partition entries and their index. The index always starts at 1.

Source

pub fn iter_mut( &mut self, ) -> impl Iterator<Item = (u32, &mut GPTPartitionEntry)>

Get a mutable iterator over the partition entries and their index. The index always starts at 1.

Source

pub fn write_protective_mbr_into<W>( writer: &mut W, sector_size: u64, ) -> Result<()>
where W: Write + Seek + ?Sized,

This function writes a protective MBR in the first sector of the disk starting at byte 446 and ending at byte 511. Any existing data will be overwritten.

See also: Self::write_bootable_protective_mbr_into.

Source

pub fn write_bootable_protective_mbr_into<W>( writer: &mut W, sector_size: u64, ) -> Result<()>
where W: Write + Seek + ?Sized,

This function writes a protective MBR in the first sector of the disk starting at byte 446 and ending at byte 511. Any existing data will be overwritten. This function differs from Self::write_protective_mbr_into in that the partition in the MBR partition table is marked as bootable. Some legacy BIOS systems do not consider a disk to be bootable if there isn’t an MBR partition marked as bootable in the MBR partition table.

Some systems will not consider a disk to be bootable in UEFI mode if the pMBR is marked as bootable, so this should only be used if booting on legacy BIOS systems is a requirement.
Source

pub fn is_primary(&self) -> bool

Returns true if the GPTHeader is a primary copy (the header is located at the beginning of the disk).

Source

pub fn is_backup(&self) -> bool

Returns true if the GPTHeader is a backup copy (the header is located at the end of the disk).

Note that when the header is a backup copy, the primary_lba is the LBA of the backup copy and the backup_lba is the LBA of the primary copy.

Trait Implementations§

Source§

impl Clone for GPT

Source§

fn clone(&self) -> GPT

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for GPT

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Index<u32> for GPT

Source§

type Output = GPTPartitionEntry

The returned type after indexing.
Source§

fn index(&self, i: u32) -> &GPTPartitionEntry

Performs the indexing (container[index]) operation. Read more
Source§

impl IndexMut<u32> for GPT

Source§

fn index_mut(&mut self, i: u32) -> &mut GPTPartitionEntry

Performs the mutable indexing (container[index]) operation. Read more
Source§

impl PartialEq for GPT

Source§

fn eq(&self, other: &GPT) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Eq for GPT

Source§

impl StructuralPartialEq for GPT

Auto Trait Implementations§

§

impl Freeze for GPT

§

impl RefUnwindSafe for GPT

§

impl Send for GPT

§

impl Sync for GPT

§

impl Unpin for GPT

§

impl UnwindSafe for GPT

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> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. 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> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.