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

Method new

block/src/vhdx/vhdx_metadata.rs:105–245  ·  view source on GitHub ↗

Parse all metadata from the provided file and store info in DiskSpec structure.

(f: &mut File, metadata_region: &RegionTableEntry)

Source from the content-addressed store, hash-verified

103 /// Parse all metadata from the provided file and store info in DiskSpec
104 /// structure.
105 pub fn new(f: &mut File, metadata_region: &RegionTableEntry) -> Result<DiskSpec> {
106 let mut disk_spec = DiskSpec::default();
107 let mut metadata_presence: u16 = 0;
108 let mut offset = 0;
109 let metadata = f.metadata().map_err(VhdxMetadataError::ReadMetadata)?;
110 disk_spec.image_size = metadata.len();
111
112 let mut buffer = [0u8; METADATA_TABLE_MAX_SIZE];
113 f.seek(SeekFrom::Start(metadata_region.file_offset))
114 .map_err(VhdxMetadataError::ReadMetadata)?;
115 f.read_exact(&mut buffer)
116 .map_err(VhdxMetadataError::ReadMetadata)?;
117
118 let metadata_header =
119 MetadataTableHeader::new(&buffer[0..size_of::<MetadataTableHeader>()])?;
120
121 offset += size_of::<MetadataTableHeader>();
122 for _ in 0..metadata_header.entry_count {
123 let metadata_entry =
124 MetadataTableEntry::new(&buffer[offset..offset + size_of::<MetadataTableEntry>()])?;
125
126 f.seek(SeekFrom::Start(
127 metadata_region.file_offset + metadata_entry.offset as u64,
128 ))
129 .map_err(VhdxMetadataError::ReadMetadata)?;
130
131 if metadata_entry.item_id
132 == Uuid::parse_str(METADATA_FILE_PARAMETER)
133 .map_err(VhdxMetadataError::InvalidUuid)?
134 {
135 disk_spec.block_size = f
136 .read_u32::<LittleEndian>()
137 .map_err(VhdxMetadataError::ReadMetadata)?;
138
139 // MUST be at least 1 MiB and not greater than 256 MiB
140 if disk_spec.block_size < BLOCK_SIZE_MIN || disk_spec.block_size > BLOCK_SIZE_MAX {
141 return Err(VhdxMetadataError::InvalidBlockSize);
142 }
143
144 // MUST be power of 2
145 if !disk_spec.block_size.is_power_of_two() {
146 return Err(VhdxMetadataError::InvalidBlockSize);
147 }
148
149 let bits = f
150 .read_u32::<LittleEndian>()
151 .map_err(VhdxMetadataError::ReadMetadata)?;
152 disk_spec.has_parent = bits & BLOCK_HAS_PARENT != 0;
153
154 metadata_presence |= METADATA_FILE_PARAMETER_PRESENT;
155 } else if metadata_entry.item_id
156 == Uuid::parse_str(METADATA_VIRTUAL_DISK_SIZE)
157 .map_err(VhdxMetadataError::InvalidUuid)?
158 {
159 disk_spec.virtual_disk_size = f
160 .read_u64::<LittleEndian>()
161 .map_err(VhdxMetadataError::ReadMetadata)?;
162

Callers

nothing calls this directly

Calls 5

newFunction · 0.85
uuid_from_guidFunction · 0.85
metadataMethod · 0.80
lenMethod · 0.45
seekMethod · 0.45

Tested by

no test coverage detected