private void WriteHeader() { long otherPos; _header.SequenceNumber++; _header.CalcChecksum(); if (_activeHeader == 1) { _fileStream.Position = 128 * Sizes.OneKiB; otherPos = 64 * Sizes.OneKiB; } else { _fileStream.Position = 64 * Sizes.OneKiB; otherPos = 128 * Sizes.OneKiB; } StreamUtilities.WriteStruct(_fileStream, _header); _fileStream.Flush(); _header.SequenceNumber++; _header.CalcChecksum(); _fileStream.Position = otherPos; StreamUtilities.WriteStruct(_fileStream, _header); _fileStream.Flush(); }
internal static Metadata Initialize(Stream metadataStream, FileParameters fileParameters, ulong diskSize, uint logicalSectorSize, uint physicalSectorSize, ParentLocator parentLocator) { MetadataTable header = new MetadataTable(); uint dataOffset = (uint)(64 * Sizes.OneKiB); dataOffset += AddEntryStruct(fileParameters, MetadataTable.FileParametersGuid, MetadataEntryFlags.IsRequired, header, dataOffset, metadataStream); dataOffset += AddEntryValue(diskSize, EndianUtilities.WriteBytesLittleEndian, MetadataTable.VirtualDiskSizeGuid, MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream); dataOffset += AddEntryValue(Guid.NewGuid(), EndianUtilities.WriteBytesLittleEndian, MetadataTable.Page83DataGuid, MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream); dataOffset += AddEntryValue(logicalSectorSize, EndianUtilities.WriteBytesLittleEndian, MetadataTable.LogicalSectorSizeGuid, MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream); dataOffset += AddEntryValue(physicalSectorSize, EndianUtilities.WriteBytesLittleEndian, MetadataTable.PhysicalSectorSizeGuid, MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream); if (parentLocator != null) { dataOffset += AddEntryStruct(parentLocator, MetadataTable.ParentLocatorGuid, MetadataEntryFlags.IsRequired, header, dataOffset, metadataStream); } metadataStream.Position = 0; StreamUtilities.WriteStruct(metadataStream, header); return(new Metadata(metadataStream)); }
private static uint AddEntryStruct <T>(T data, Guid id, MetadataEntryFlags flags, MetadataTable header, uint dataOffset, Stream stream) where T : IByteArraySerializable { MetadataEntryKey key = new MetadataEntryKey(id, (flags & MetadataEntryFlags.IsUser) != 0); MetadataEntry entry = new MetadataEntry(); entry.ItemId = id; entry.Offset = dataOffset; entry.Length = (uint)data.Size; entry.Flags = flags; header.Entries[key] = entry; stream.Position = dataOffset; StreamUtilities.WriteStruct(stream, data); return(entry.Length); }
private static void InitializeDynamicInternal(Stream stream, long capacity, long blockSize) { if (blockSize < Sizes.OneMiB || blockSize > Sizes.OneMiB * 256 || !Utilities.IsPowerOfTwo(blockSize)) { throw new ArgumentOutOfRangeException(nameof(blockSize), blockSize, "BlockSize must be a power of 2 between 1MB and 256MB"); } int logicalSectorSize = 512; int physicalSectorSize = 4096; long chunkRatio = 0x800000L * logicalSectorSize / blockSize; long dataBlocksCount = MathUtilities.Ceil(capacity, blockSize); long sectorBitmapBlocksCount = MathUtilities.Ceil(dataBlocksCount, chunkRatio); long totalBatEntriesDynamic = dataBlocksCount + (dataBlocksCount - 1) / chunkRatio; FileHeader fileHeader = new FileHeader { Creator = ".NET DiscUtils" }; long fileEnd = Sizes.OneMiB; VhdxHeader header1 = new VhdxHeader(); header1.SequenceNumber = 0; header1.FileWriteGuid = Guid.NewGuid(); header1.DataWriteGuid = Guid.NewGuid(); header1.LogGuid = Guid.Empty; header1.LogVersion = 0; header1.Version = 1; header1.LogLength = (uint)Sizes.OneMiB; header1.LogOffset = (ulong)fileEnd; header1.CalcChecksum(); fileEnd += header1.LogLength; VhdxHeader header2 = new VhdxHeader(header1); header2.SequenceNumber = 1; header2.CalcChecksum(); RegionTable regionTable = new RegionTable(); RegionEntry metadataRegion = new RegionEntry(); metadataRegion.Guid = RegionEntry.MetadataRegionGuid; metadataRegion.FileOffset = fileEnd; metadataRegion.Length = (uint)Sizes.OneMiB; metadataRegion.Flags = RegionFlags.Required; regionTable.Regions.Add(metadataRegion.Guid, metadataRegion); fileEnd += metadataRegion.Length; RegionEntry batRegion = new RegionEntry(); batRegion.Guid = RegionEntry.BatGuid; batRegion.FileOffset = 3 * Sizes.OneMiB; batRegion.Length = (uint)MathUtilities.RoundUp(totalBatEntriesDynamic * 8, Sizes.OneMiB); batRegion.Flags = RegionFlags.Required; regionTable.Regions.Add(batRegion.Guid, batRegion); fileEnd += batRegion.Length; stream.Position = 0; StreamUtilities.WriteStruct(stream, fileHeader); stream.Position = 64 * Sizes.OneKiB; StreamUtilities.WriteStruct(stream, header1); stream.Position = 128 * Sizes.OneKiB; StreamUtilities.WriteStruct(stream, header2); stream.Position = 192 * Sizes.OneKiB; StreamUtilities.WriteStruct(stream, regionTable); stream.Position = 256 * Sizes.OneKiB; StreamUtilities.WriteStruct(stream, regionTable); // Set stream to min size stream.Position = fileEnd - 1; stream.WriteByte(0); // Metadata FileParameters fileParams = new FileParameters { BlockSize = (uint)blockSize, Flags = FileParametersFlags.None }; ParentLocator parentLocator = new ParentLocator(); Stream metadataStream = new SubStream(stream, metadataRegion.FileOffset, metadataRegion.Length); Metadata metadata = Metadata.Initialize(metadataStream, fileParams, (ulong)capacity, (uint)logicalSectorSize, (uint)physicalSectorSize, null); }