• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

google / gpt-disk-rs / 14182859342

31 Mar 2025 10:40PM CUT coverage: 94.803%. Remained the same
14182859342

Pull #277

github

web-flow
Merge 9a5384971 into 32b4a7e87
Pull Request #277: uguid: Unconditionally use the Error trait

1441 of 1520 relevant lines covered (94.8%)

13.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.37
/gpt_disk_types/src/header.rs
1
// Copyright 2022 Google LLC
2
//
3
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6
// option. This file may not be copied, modified, or distributed
7
// except according to those terms.
8

9
use crate::{
10
    Crc32, GptPartitionEntry, GptPartitionEntryArrayLayout,
11
    GptPartitionEntrySize, GptPartitionEntrySizeError, Guid, LbaLe, U32Le,
12
    U64Le,
13
};
14
use core::fmt::{self, Display, Formatter};
15
use core::mem;
16

17
#[cfg(feature = "bytemuck")]
18
use bytemuck::{bytes_of, Pod, Zeroable};
19

20
/// GPT header signature.
21
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
22
#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
×
23
#[repr(transparent)]
24
pub struct GptHeaderSignature(pub U64Le);
25

26
impl Display for GptHeaderSignature {
27
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
4✔
28
        f.write_str("Signature(")?;
4✔
29
        if *self == Self::EFI_COMPATIBLE_PARTITION_TABLE_HEADER {
4✔
30
            f.write_str("\"EFI PART\"")?;
3✔
31
        } else {
32
            write!(f, "Invalid: {:#016x}", self.0)?;
1✔
33
        }
34
        f.write_str(")")
4✔
35
    }
4✔
36
}
37

38
impl GptHeaderSignature {
39
    /// EFI-compatible partition table header. This is the only valid
40
    /// signature.
41
    pub const EFI_COMPATIBLE_PARTITION_TABLE_HEADER: Self =
42
        Self(U64Le(*b"EFI PART"));
43

44
    /// Convert to [`u64`] with the host's endianness.
45
    #[must_use]
46
    pub const fn to_u64(self) -> u64 {
1✔
47
        self.0.to_u64()
1✔
48
    }
1✔
49
}
50

51
impl Default for GptHeaderSignature {
52
    fn default() -> Self {
16✔
53
        Self::EFI_COMPATIBLE_PARTITION_TABLE_HEADER
16✔
54
    }
16✔
55
}
56

57
/// GPT header revision.
58
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
59
#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
×
60
#[repr(transparent)]
61
pub struct GptHeaderRevision(pub U32Le);
62

63
impl GptHeaderRevision {
64
    /// Version 1.0. This is the only valid revision.
65
    pub const VERSION_1_0: Self = Self(U32Le::from_u32(0x0001_0000));
66

67
    /// Get the major part of the version.
68
    #[allow(clippy::missing_panics_doc)]
69
    #[must_use]
70
    pub fn major(self) -> u16 {
2✔
71
        u16::from_le_bytes(self.0 .0[2..4].try_into().unwrap())
2✔
72
    }
2✔
73

74
    /// Get the minor part of the version.
75
    #[allow(clippy::missing_panics_doc)]
76
    #[must_use]
77
    pub fn minor(self) -> u16 {
2✔
78
        u16::from_le_bytes(self.0 .0[0..2].try_into().unwrap())
2✔
79
    }
2✔
80
}
81

82
impl Default for GptHeaderRevision {
83
    fn default() -> Self {
16✔
84
        Self::VERSION_1_0
16✔
85
    }
16✔
86
}
87

88
impl Display for GptHeaderRevision {
89
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1✔
90
        write!(f, "{:#08x}", self.0)
1✔
91
    }
1✔
92
}
93

94
/// GPT header that appears near the start and end of a GPT-formatted disk.
95
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd)]
96
#[cfg_attr(feature = "bytemuck", derive(Pod, Zeroable))]
×
97
#[repr(C, packed)]
98
pub struct GptHeader {
99
    /// Magic signature for the header. In a valid header this must be
100
    /// [`GptHeaderSignature::EFI_COMPATIBLE_PARTITION_TABLE_HEADER`].
101
    pub signature: GptHeaderSignature,
102

103
    /// Revision number for the header. In a valid header this must be
104
    /// [`GptHeaderRevision::VERSION_1_0`].
105
    pub revision: GptHeaderRevision,
106

107
    /// Size of the header in bytes. In a valid header this must be
108
    /// greater than or equal to 92 bytes, and less than or equal to the
109
    /// block size.
110
    pub header_size: U32Le,
111

112
    /// CRC32 checksum of the entire header. When calculating the
113
    /// checksum, this field is included in the checksum as four zero
114
    /// bytes.
115
    pub header_crc32: Crc32,
116

117
    /// Reserved bytes. In a valid header these must be all zero.
118
    pub reserved: U32Le,
119

120
    /// The LBA that contains this header.
121
    pub my_lba: LbaLe,
122

123
    /// The LBA that contains the alternate header.
124
    pub alternate_lba: LbaLe,
125

126
    /// First LBA that can be used for the data of a partition in the
127
    /// partition entry array.
128
    pub first_usable_lba: LbaLe,
129

130
    /// Last LBA that can be used for the data of a partition in the
131
    /// partition entry array.
132
    pub last_usable_lba: LbaLe,
133

134
    /// Unique ID for the disk.
135
    pub disk_guid: Guid,
136

137
    /// First LBA of the partition entry array.
138
    pub partition_entry_lba: LbaLe,
139

140
    /// Number of partitions in the partition entry array.
141
    pub number_of_partition_entries: U32Le,
142

143
    /// Size in bytes of each entry in the partition entry array.
144
    pub size_of_partition_entry: U32Le,
145

146
    /// CRC32 checksum of the partition entry array.
147
    pub partition_entry_array_crc32: Crc32,
148
}
149

150
impl GptHeader {
151
    /// Check if the header's signature matches
152
    /// [`GptHeaderSignature::EFI_COMPATIBLE_PARTITION_TABLE_HEADER`].
153
    #[must_use]
154
    pub fn is_signature_valid(&self) -> bool {
1✔
155
        self.signature
1✔
156
            == GptHeaderSignature::EFI_COMPATIBLE_PARTITION_TABLE_HEADER
1✔
157
    }
1✔
158

159
    /// Calculate the header's CRC32 checksum. This returns the checksum
160
    /// but does not update the checksum field in the header.
161
    #[cfg(feature = "bytemuck")]
162
    #[must_use]
163
    pub fn calculate_header_crc32(&self) -> Crc32 {
2✔
164
        let crc = crc::Crc::<u32>::new(&Crc32::ALGORITHM);
2✔
165
        let mut digest = crc.digest();
2✔
166
        digest.update(bytes_of(&self.signature));
2✔
167
        digest.update(bytes_of(&self.revision));
2✔
168
        digest.update(bytes_of(&self.header_size));
2✔
169
        digest.update(&[0u8; 4]); // Zeroes for the `header_crc32` field.
2✔
170
        digest.update(bytes_of(&self.reserved));
2✔
171
        digest.update(bytes_of(&self.my_lba));
2✔
172
        digest.update(bytes_of(&self.alternate_lba));
2✔
173
        digest.update(bytes_of(&self.first_usable_lba));
2✔
174
        digest.update(bytes_of(&self.last_usable_lba));
2✔
175
        digest.update(bytes_of(&{ self.disk_guid }));
2✔
176
        digest.update(bytes_of(&self.partition_entry_lba));
2✔
177
        digest.update(bytes_of(&self.number_of_partition_entries));
2✔
178
        digest.update(bytes_of(&self.size_of_partition_entry));
2✔
179
        digest.update(bytes_of(&self.partition_entry_array_crc32));
2✔
180
        Crc32(U32Le(digest.finalize().to_le_bytes()))
2✔
181
    }
2✔
182

183
    /// Update the header's CRC32 checksum.
184
    #[cfg(feature = "bytemuck")]
185
    pub fn update_header_crc32(&mut self) {
1✔
186
        self.header_crc32 = self.calculate_header_crc32();
1✔
187
    }
1✔
188

189
    /// Get the [`GptPartitionEntryArrayLayout`] for this header.
190
    pub fn get_partition_entry_array_layout(
10✔
191
        &self,
10✔
192
    ) -> Result<GptPartitionEntryArrayLayout, GptPartitionEntrySizeError> {
10✔
193
        Ok(GptPartitionEntryArrayLayout {
10✔
194
            start_lba: self.partition_entry_lba.into(),
10✔
195
            entry_size: GptPartitionEntrySize::new(
10✔
196
                self.size_of_partition_entry.to_u32(),
10✔
197
            )?,
10✔
198
            num_entries: self.number_of_partition_entries.to_u32(),
9✔
199
        })
200
    }
10✔
201
}
202

203
impl Default for GptHeader {
204
    fn default() -> Self {
15✔
205
        Self {
15✔
206
            signature: GptHeaderSignature::default(),
15✔
207
            revision: GptHeaderRevision::default(),
15✔
208
            header_size: U32Le::from_u32(
15✔
209
                u32::try_from(mem::size_of::<Self>()).unwrap(),
15✔
210
            ),
15✔
211
            header_crc32: Crc32::default(),
15✔
212
            reserved: U32Le::default(),
15✔
213
            my_lba: LbaLe::default(),
15✔
214
            alternate_lba: LbaLe::default(),
15✔
215
            first_usable_lba: LbaLe::default(),
15✔
216
            last_usable_lba: LbaLe::default(),
15✔
217
            disk_guid: Guid::default(),
15✔
218
            partition_entry_lba: LbaLe::default(),
15✔
219
            number_of_partition_entries: U32Le::default(),
15✔
220
            size_of_partition_entry: U32Le::from_u32(
15✔
221
                u32::try_from(mem::size_of::<GptPartitionEntry>()).unwrap(),
15✔
222
            ),
15✔
223
            partition_entry_array_crc32: Crc32::default(),
15✔
224
        }
15✔
225
    }
15✔
226
}
227

228
impl Display for GptHeader {
229
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
3✔
230
        write!(f, "GptHeader {{ signature: {}", self.signature)?;
3✔
231
        write!(f, ", revision: {:#x}", self.revision.0)?;
3✔
232
        write!(f, ", header_size: {}", self.header_size.to_u32())?;
3✔
233
        write!(f, ", header_crc32: {:#x}", self.header_crc32)?;
3✔
234
        write!(f, ", my_lba: {}", self.my_lba)?;
3✔
235
        write!(f, ", alternate_lba: {}", self.alternate_lba)?;
3✔
236
        write!(f, ", first_usable_lba: {}", self.first_usable_lba)?;
3✔
237
        write!(f, ", last_usable_lba: {}", self.last_usable_lba)?;
3✔
238
        write!(f, ", disk_guid: {}", &{ self.disk_guid })?;
3✔
239
        write!(f, ", partition_entry_lba: {}", self.partition_entry_lba)?;
3✔
240
        write!(
3✔
241
            f,
3✔
242
            ", number_of_partition_entries: {}",
3✔
243
            self.number_of_partition_entries
3✔
244
        )?;
3✔
245
        write!(
3✔
246
            f,
3✔
247
            ", size_of_partition_entry: {}",
3✔
248
            self.size_of_partition_entry
3✔
249
        )?;
3✔
250
        write!(
3✔
251
            f,
3✔
252
            ", partition_entry_array_crc32: {:#x}",
3✔
253
            self.partition_entry_array_crc32
3✔
254
        )?;
3✔
255
        f.write_str(" }")
3✔
256
    }
3✔
257
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc