MCPcopy Create free account
hub / github.com/cloud-hypervisor/cloud-hypervisor / read_header_extensions

Method read_header_extensions

block/src/qcow/header.rs:212–269  ·  view source on GitHub ↗

Read header extensions, optionally collecting feature names for error reporting.

(
        f: &mut RawFile,
        header: &mut QcowHeader,
        mut feature_table: Option<&mut Vec<(u8, String)>>,
    )

Source from the content-addressed store, hash-verified

210impl QcowHeader {
211 /// Read header extensions, optionally collecting feature names for error reporting.
212 pub(super) fn read_header_extensions(
213 f: &mut RawFile,
214 header: &mut QcowHeader,
215 mut feature_table: Option<&mut Vec<(u8, String)>>,
216 ) -> Result<()> {
217 // Extensions start directly after the header
218 f.seek(SeekFrom::Start(header.header_size as u64))
219 .map_err(Error::ReadingHeader)?;
220
221 loop {
222 let ext_type = u32::read_be(f).map_err(Error::ReadingHeader)?;
223 if ext_type == HEADER_EXT_END {
224 break;
225 }
226
227 let ext_length = u32::read_be(f).map_err(Error::ReadingHeader)?;
228
229 match ext_type {
230 HEADER_EXT_BACKING_FORMAT => {
231 let mut format_bytes = vec![0u8; ext_length as usize];
232 f.read_exact(&mut format_bytes)
233 .map_err(Error::ReadingHeader)?;
234 let format_str = String::from_utf8(format_bytes)
235 .map_err(|err| Error::InvalidBackingFileName(err.utf8_error()))?;
236 if let Some(backing_file) = &mut header.backing_file {
237 backing_file.format = Some(format_str.parse()?);
238 }
239 }
240 HEADER_EXT_FEATURE_NAME_TABLE if feature_table.is_some() => {
241 const FEATURE_NAME_ENTRY_SIZE: usize = 1 + 1 + 46; // type + bit + name
242 let mut data = vec![0u8; ext_length as usize];
243 f.read_exact(&mut data).map_err(Error::ReadingHeader)?;
244 let table = feature_table.as_mut().unwrap();
245 for entry in data.chunks_exact(FEATURE_NAME_ENTRY_SIZE) {
246 if entry[0] == FEAT_TYPE_INCOMPATIBLE {
247 let bit_number = entry[1];
248 let name_bytes = &entry[2..];
249 let name_len = name_bytes.iter().position(|&b| b == 0).unwrap_or(46);
250 let name = String::from_utf8_lossy(&name_bytes[..name_len]).to_string();
251 table.push((bit_number, name));
252 }
253 }
254 }
255 _ => {
256 // Skip unknown extension
257 f.seek(SeekFrom::Current(ext_length as i64))
258 .map_err(Error::ReadingHeader)?;
259 }
260 }
261
262 // Skip to the next 8 byte boundary
263 let padding = (8 - (ext_length % 8)) % 8;
264 f.seek(SeekFrom::Current(padding as i64))
265 .map_err(Error::ReadingHeader)?;
266 }
267
268 Ok(())
269 }

Callers

nothing calls this directly

Calls 4

iterMethod · 0.80
seekMethod · 0.45
parseMethod · 0.45
pushMethod · 0.45

Tested by

no test coverage detected