@@ -80,7 +80,7 @@ use std::collections::HashSet;
80
80
use std:: fmt;
81
81
use std:: io;
82
82
use std:: io:: { Read , Seek , SeekFrom , Write } ;
83
- use std:: ops:: { Index , IndexMut } ;
83
+ use std:: ops:: { Index , IndexMut , RangeInclusive } ;
84
84
use thiserror:: Error ;
85
85
86
86
/// Linux specific helpers
@@ -146,9 +146,15 @@ pub enum Error {
146
146
/// included.
147
147
#[ error( "invalid partition number: {0}" ) ]
148
148
InvalidPartitionNumber ( u32 ) ,
149
+ /// An error that occurs when the user attempts to access information for an unused partition.
150
+ #[ error( "unused partition" ) ]
151
+ UnusedPartition ,
149
152
/// An operation that required to find a partition, was unable to find that partition.
150
153
#[ error( "partition not found" ) ]
151
154
PartitionNotFound ,
155
+ /// An arithmetic operation overflowed.
156
+ #[ error( "an arithmetic operation overflowed" ) ]
157
+ Overflow ,
152
158
}
153
159
154
160
/// The result of reading, writing or managing a GPT.
@@ -575,6 +581,43 @@ impl GPTPartitionEntry {
575
581
576
582
Ok ( self . ending_lba - self . starting_lba + 1 )
577
583
}
584
+
585
+ /// Get the range of sectors covered by a partition.
586
+ ///
587
+ /// # Errors
588
+ ///
589
+ /// This function will return an error if the partition is unused or if
590
+ /// `ending_lba` is lesser than the `starting_lba`.
591
+ ///
592
+ /// # Examples
593
+ ///
594
+ /// ```
595
+ /// let ss = 512;
596
+ /// let data = vec![0; 100 * ss as usize];
597
+ /// let mut cur = std::io::Cursor::new(data);
598
+ /// let mut gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16])
599
+ /// .expect("could not create partition table");
600
+ /// gpt[1] = gptman::GPTPartitionEntry {
601
+ /// partition_type_guid: [0xff; 16],
602
+ /// unique_partition_guid: [0xff; 16],
603
+ /// starting_lba: 2048,
604
+ /// ending_lba: 4096,
605
+ /// attribute_bits: 0,
606
+ /// partition_name: "A Robot Named Fight!".into(),
607
+ /// };
608
+ ///
609
+ /// assert_eq!(gpt[1].range().unwrap(), 2048..=4096);
610
+ /// ```
611
+ pub fn range ( & self ) -> Result < RangeInclusive < u64 > > {
612
+ if self . is_unused ( ) {
613
+ return Err ( Error :: UnusedPartition ) ;
614
+ }
615
+ if self . ending_lba < self . starting_lba {
616
+ return Err ( Error :: InvalidPartitionBoundaries ) ;
617
+ }
618
+
619
+ Ok ( self . starting_lba ..=self . ending_lba )
620
+ }
578
621
}
579
622
580
623
/// A type representing a GUID partition table including its partitions, the sector size of the
@@ -1076,6 +1119,56 @@ impl GPT {
1076
1119
. ok_or ( Error :: NoSpaceLeft )
1077
1120
}
1078
1121
1122
+ /// Get the range of bytes covered by a partition.
1123
+ ///
1124
+ /// # Errors
1125
+ ///
1126
+ /// This function will return an error if the partition number is invalid, or if
1127
+ /// the partition is unused, or if the partition's `ending_lba` is less than its
1128
+ /// `starting_lba`.
1129
+ ///
1130
+ /// # Examples
1131
+ ///
1132
+ /// ```
1133
+ /// let ss = 512;
1134
+ /// let data = vec![0; 100 * ss as usize];
1135
+ /// let mut cur = std::io::Cursor::new(data);
1136
+ /// let mut gpt = gptman::GPT::new_from(&mut cur, ss as u64, [0xff; 16])
1137
+ /// .expect("could not create partition table");
1138
+ /// gpt[1] = gptman::GPTPartitionEntry {
1139
+ /// partition_type_guid: [0xff; 16],
1140
+ /// unique_partition_guid: [0xff; 16],
1141
+ /// starting_lba: 2048,
1142
+ /// ending_lba: 2048,
1143
+ /// attribute_bits: 0,
1144
+ /// partition_name: "A Robot Named Fight!".into(),
1145
+ /// };
1146
+ ///
1147
+ /// assert_eq!(gpt.get_partition_byte_range(1).unwrap(), 1048576..=1049087);
1148
+ /// ```
1149
+ pub fn get_partition_byte_range ( & self , partition_number : u32 ) -> Result < RangeInclusive < u64 > > {
1150
+ if partition_number == 0 || partition_number > self . header . number_of_partition_entries {
1151
+ return Err ( Error :: InvalidPartitionNumber ( partition_number) ) ;
1152
+ }
1153
+ let partition = & self [ partition_number] ;
1154
+
1155
+ let sector_range = partition. range ( ) ?;
1156
+
1157
+ let start_byte = sector_range
1158
+ . start ( )
1159
+ . checked_mul ( self . sector_size )
1160
+ . ok_or ( Error :: Overflow ) ?;
1161
+ // Sector ranges are inclusive, so to get the position of the end byte we need
1162
+ // to add the size of another sector, less one byte because the byte range
1163
+ // returned from this function is also inclusive.
1164
+ let end_byte = sector_range
1165
+ . end ( )
1166
+ . checked_mul ( self . sector_size )
1167
+ . and_then ( |v| v. checked_add ( self . sector_size - 1 ) )
1168
+ . ok_or ( Error :: Overflow ) ?;
1169
+ Ok ( start_byte..=end_byte)
1170
+ }
1171
+
1079
1172
/// Sort the partition entries in the array by the starting LBA.
1080
1173
pub fn sort ( & mut self ) {
1081
1174
self . partitions
0 commit comments