Skip to content

Commit a3c0ac3

Browse files
authored
Add helpers for resizing (#36)
* Add method update_from() to update the disk_size of the header * Add method get_maximum_partition_size_for
1 parent 74eb818 commit a3c0ac3

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/lib.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,18 @@ impl MBR {
479479
})
480480
}
481481

482+
/// Updates the header to match the specifications of the seeker given in argument.
483+
/// `disk_size` will be updated after this operation.
484+
pub fn update_from<S: ?Sized>(&mut self, seeker: &mut S) -> Result<()>
485+
where
486+
S: Seek,
487+
{
488+
self.disk_size =
489+
u32::try_from(seeker.seek(SeekFrom::End(0))? / u64::from(self.sector_size))
490+
.unwrap_or(u32::max_value());
491+
Ok(())
492+
}
493+
482494
fn find_alignment(header: &MBRHeader, logical_partitions: &[LogicalPartition]) -> u32 {
483495
let lbas = header
484496
.iter()
@@ -871,6 +883,49 @@ impl MBR {
871883
.ok_or(Error::NoSpaceLeft)
872884
}
873885

886+
/// Gets the maximum size (in sectors) a partition can grow to without overlapping another
887+
/// partition.
888+
/// This function will automatically align with the alignment defined in the `MBR`.
889+
///
890+
/// # Examples:
891+
/// Basic usage:
892+
/// ```
893+
/// let ss = 512;
894+
/// let data = vec![0; 100 * ss as usize];
895+
/// let mut cur = std::io::Cursor::new(data);
896+
/// let mut mbr = mbrman::MBR::new_from(&mut cur, ss as u32, [0xff; 4])
897+
/// .expect("could not create partition table");
898+
///
899+
/// // NOTE: align to the sectors, so we can use every last one of them
900+
/// // NOTE: this is only for the demonstration purpose, this is not recommended
901+
/// mbr.align = 1;
902+
///
903+
/// mbr[1] = mbrman::MBRPartitionEntry {
904+
/// boot: mbrman::BOOT_INACTIVE,
905+
/// first_chs: mbrman::CHS::empty(),
906+
/// sys: 0x83,
907+
/// last_chs: mbrman::CHS::empty(),
908+
/// starting_lba: mbr.find_optimal_place(1).unwrap(),
909+
/// sectors: 1,
910+
/// };
911+
///
912+
/// assert_eq!(
913+
/// mbr.get_maximum_partition_size_for(1)
914+
/// .expect("could not find a place to put the partition"),
915+
/// mbr.disk_size - 1
916+
/// );
917+
/// ```
918+
pub fn get_maximum_partition_size_for(&mut self, i: usize) -> Result<u32> {
919+
let spots = self.find_free_sectors();
920+
let p = self.get_mut(i).ok_or(Error::PartitionNotFound)?;
921+
let free_sectors = spots
922+
.into_iter()
923+
.find(|(i, _)| *i == p.starting_lba + p.sectors)
924+
.map(|(_, l)| l)
925+
.unwrap_or(0);
926+
Ok(p.sectors + free_sectors)
927+
}
928+
874929
/// Push a new logical partition to the end of the extended partition list. This function will
875930
/// take care of creating the EBR for you. The EBR will be located at `starting_lba` (provided
876931
/// in input) and the logical partition itself will be located a block further to stay
@@ -1993,6 +2048,20 @@ mod tests {
19932048
Error::InvalidBootFlag
19942049
));
19952050
}
2051+
2052+
#[test]
2053+
fn update_from() {
2054+
let ss = 512_u32;
2055+
let data = vec![0; 10 * ss as usize];
2056+
let mut cur = Cursor::new(data);
2057+
let mut mbr = MBR::new_from(&mut cur, ss, [0xff; 4]).unwrap();
2058+
assert_eq!(mbr.disk_size, 10);
2059+
let mut data = cur.into_inner();
2060+
data.resize(20 * ss as usize, 0);
2061+
let mut cur = Cursor::new(data);
2062+
mbr.update_from(&mut cur).unwrap();
2063+
assert_eq!(mbr.disk_size, 20);
2064+
}
19962065
}
19972066

19982067
#[cfg(doctest)]

0 commit comments

Comments
 (0)