@@ -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