@@ -46,6 +46,10 @@ pub enum Change {
4646
4747/// A disk partitioning planner.
4848pub struct Planner {
49+ /// First usable LBA position on disk in bytes
50+ usable_start : u64 ,
51+ /// Last usable LBA position on disk in bytes
52+ usable_end : u64 ,
4953 /// The original block device state that we're planning changes for
5054 device : BlockDevice ,
5155 /// Stack of changes that can be undone
@@ -192,30 +196,49 @@ impl Planner {
192196 /// Creates a new partitioning planner for the given disk.
193197 pub fn new ( device : BlockDevice ) -> Self {
194198 debug ! ( "Creating new partition planner for device of size {}" , device. size( ) ) ;
199+
195200 // Extract original regions from device
196201 let original_regions = device
197202 . partitions ( )
198203 . iter ( )
199204 . map ( |p| Region :: new ( p. start , p. end ) )
200205 . collect ( ) ;
206+
201207 Self {
208+ usable_start : 0 ,
209+ usable_end : device. size ( ) ,
202210 device,
203211 changes : VecDeque :: new ( ) ,
204212 original_regions,
205213 }
206214 }
207215
216+ /// Set the usable disk region offsets
217+ pub fn with_start_offset ( self , offset : u64 ) -> Self {
218+ Self {
219+ usable_start : offset,
220+ ..self
221+ }
222+ }
223+
224+ /// Set the usable disk region offsets
225+ pub fn with_end_offset ( self , offset : u64 ) -> Self {
226+ Self {
227+ usable_end : offset,
228+ ..self
229+ }
230+ }
231+
208232 /// Get a human readable description of pending changes
209233 pub fn describe_changes ( & self ) -> String {
210234 if self . changes . is_empty ( ) {
211235 return "No pending changes" . to_string ( ) ;
212236 }
213237
214- let disk_size = self . device . size ( ) ;
215238 let mut description = "Pending changes:\n " . to_string ( ) ;
216239
217240 for ( i, change) in self . changes . iter ( ) . enumerate ( ) {
218- description. push_str ( & format ! ( " {}: {}\n " , i + 1 , change. describe( disk_size ) ) ) ;
241+ description. push_str ( & format ! ( " {}: {}\n " , i + 1 , change. describe( self . usable_size ( ) ) ) ) ;
219242 }
220243
221244 description
@@ -272,9 +295,9 @@ impl Planner {
272295 let aligned_end = align_down ( end, PARTITION_ALIGNMENT ) ;
273296 debug ! ( "Aligned positions: {}..{}" , aligned_start, aligned_end) ;
274297
275- // Validate bounds
276- if aligned_end > self . device . size ( ) {
277- warn ! ( "Partition would exceed disk bounds " ) ;
298+ // Validate bounds against usable disk region
299+ if aligned_start < self . usable_start || aligned_end > self . usable_end {
300+ warn ! ( "Partition would be outside usable disk region " ) ;
278301 return Err ( PlanError :: RegionOutOfBounds {
279302 start : aligned_start,
280303 end : aligned_end,
@@ -321,8 +344,8 @@ impl Planner {
321344 if index >= self . original_regions . len ( ) {
322345 warn ! ( "Invalid partition index {}" , index) ;
323346 return Err ( PlanError :: RegionOutOfBounds {
324- start : 0 ,
325- end : self . device . size ( ) ,
347+ start : self . usable_start ,
348+ end : self . usable_size ( ) ,
326349 } ) ;
327350 }
328351
@@ -362,6 +385,17 @@ impl Planner {
362385 pub fn original_device ( & self ) -> & BlockDevice {
363386 & self . device
364387 }
388+
389+ /// Get the size of the usable disk region in bytes
390+ pub fn usable_size ( & self ) -> u64 {
391+ self . usable_end - self . usable_start
392+ }
393+
394+ /// Get the usable disk region offsets
395+ pub fn offsets ( & self ) -> ( u64 , u64 ) {
396+ ( self . usable_start , self . usable_end )
397+ }
398+
365399 /// Plan to initialize a clean partition layout
366400 pub fn plan_initialize_disk ( & mut self ) -> Result < ( ) , PlanError > {
367401 debug ! ( "Planning to create new GPT partition table" ) ;
0 commit comments