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, Utilities.WriteBytesLittleEndian, MetadataTable.VirtualDiskSizeGuid, MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream); dataOffset += AddEntryValue(Guid.NewGuid(), Utilities.WriteBytesLittleEndian, MetadataTable.Page83DataGuid, MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream); dataOffset += AddEntryValue(logicalSectorSize, Utilities.WriteBytesLittleEndian, MetadataTable.LogicalSectorSizeGuid, MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream); dataOffset += AddEntryValue(physicalSectorSize, Utilities.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; Utilities.WriteStruct(metadataStream, header); return(new Metadata(metadataStream)); }
public Chunk(Stream bat, SparseStream file, FreeSpaceTable freeSpace, FileParameters fileParameters, int chunk, int blocksPerChunk) { _bat = bat; _file = file; _freeSpace = freeSpace; _fileParameters = fileParameters; _chunk = chunk; _blocksPerChunk = blocksPerChunk; _bat.Position = _chunk * (_blocksPerChunk + 1) * 8; _batData = Utilities.ReadFully(bat, (_blocksPerChunk + 1) * 8); }
public ContentStream(SparseStream fileStream, Stream batStream, FreeSpaceTable freeSpaceTable, Metadata metadata, long length, SparseStream parentStream, Ownership ownsParent) { _fileStream = fileStream; _batStream = batStream; _freeSpaceTable = freeSpaceTable; _metadata = metadata; _fileParameters = _metadata.FileParameters; _length = length; _parentStream = parentStream; _ownsParent = ownsParent; _chunks = new ObjectCache<int, Chunk>(); }
public Metadata(Stream regionStream) { _regionStream = regionStream; _regionStream.Position = 0; _table = Utilities.ReadStruct <MetadataTable>(_regionStream); _fileParams = ReadStruct <FileParameters>(MetadataTable.FileParametersGuid, false); _diskSize = ReadValue <ulong>(MetadataTable.VirtualDiskSizeGuid, false, Utilities.ToUInt64LittleEndian); _page83Data = ReadValue <Guid>(MetadataTable.Page83DataGuid, false, Utilities.ToGuidLittleEndian); _logicalSectorSize = ReadValue <uint>(MetadataTable.LogicalSectorSizeGuid, false, Utilities.ToUInt32LittleEndian); _physicalSectorSize = ReadValue <uint>(MetadataTable.PhysicalSectorSizeGuid, false, Utilities.ToUInt32LittleEndian); _parentLocator = ReadStruct <ParentLocator>(MetadataTable.ParentLocatorGuid, false); }
public ContentStream(SparseStream fileStream, Stream batStream, FreeSpaceTable freeSpaceTable, Metadata metadata, long length, SparseStream parentStream, Ownership ownsParent) { _fileStream = fileStream; _batStream = batStream; _freeSpaceTable = freeSpaceTable; _metadata = metadata; _fileParameters = _metadata.FileParameters; _length = length; _parentStream = parentStream; _ownsParent = ownsParent; _chunks = new ObjectCache <int, Chunk>(); }
private static void InitializeDynamicInternal(Stream stream, long capacity, long blockSize) { if (blockSize < Sizes.OneMiB || blockSize > Sizes.OneMiB * 256 || !Utilities.IsPowerOfTwo(blockSize)) { throw new ArgumentOutOfRangeException("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 = Utilities.Ceil(capacity, blockSize); long sectorBitmapBlocksCount = Utilities.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)Utilities.RoundUp(totalBatEntriesDynamic * 8, Sizes.OneMiB); batRegion.Flags = RegionFlags.Required; regionTable.Regions.Add(batRegion.Guid, batRegion); fileEnd += batRegion.Length; stream.Position = 0; Utilities.WriteStruct(stream, fileHeader); stream.Position = 64 * Sizes.OneKiB; Utilities.WriteStruct(stream, header1); stream.Position = 128 * Sizes.OneKiB; Utilities.WriteStruct(stream, header2); stream.Position = 192 * Sizes.OneKiB; Utilities.WriteStruct(stream, regionTable); stream.Position = 256 * Sizes.OneKiB; Utilities.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); }
internal override List<BuilderExtent> FixExtents(out long totalLength) { if (_diskType != DiskType.Dynamic) { throw new NotSupportedException("Creation of only dynamic disks currently implemented"); } List<BuilderExtent> extents = new List<BuilderExtent>(); int logicalSectorSize = 512; int physicalSectorSize = 4096; long chunkRatio = (0x800000L * logicalSectorSize) / _blockSize; long dataBlocksCount = Utilities.Ceil(_content.Length, _blockSize); long sectorBitmapBlocksCount = Utilities.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 = fileEnd; batRegion.Length = (uint)Utilities.RoundUp(totalBatEntriesDynamic * 8, Sizes.OneMiB); batRegion.Flags = RegionFlags.Required; regionTable.Regions.Add(batRegion.Guid, batRegion); fileEnd += batRegion.Length; extents.Add(ExtentForStruct(fileHeader, 0)); extents.Add(ExtentForStruct(header1, 64 * Sizes.OneKiB)); extents.Add(ExtentForStruct(header2, 128 * Sizes.OneKiB)); extents.Add(ExtentForStruct(regionTable, 192 * Sizes.OneKiB)); extents.Add(ExtentForStruct(regionTable, 256 * Sizes.OneKiB)); // Metadata FileParameters fileParams = new FileParameters() { BlockSize = (uint)_blockSize, Flags = FileParametersFlags.None }; ParentLocator parentLocator = new ParentLocator(); byte[] metadataBuffer = new byte[metadataRegion.Length]; MemoryStream metadataStream = new MemoryStream(metadataBuffer); Metadata.Initialize(metadataStream, fileParams, (ulong)_content.Length, (uint)logicalSectorSize, (uint)physicalSectorSize, null); extents.Add(new BuilderBufferExtent(metadataRegion.FileOffset, metadataBuffer)); List<Range<long, long>> presentBlocks = new List<Range<long, long>>(StreamExtent.Blocks(_content.Extents, _blockSize)); // BAT BlockAllocationTableBuilderExtent batExtent = new BlockAllocationTableBuilderExtent(batRegion.FileOffset, batRegion.Length, presentBlocks, fileEnd, _blockSize, chunkRatio); extents.Add(batExtent); // Stream contents foreach (var range in presentBlocks) { long substreamStart = range.Offset * _blockSize; long substreamCount = Math.Min(_content.Length - substreamStart, range.Count * _blockSize); SubStream dataSubStream = new SubStream(_content, substreamStart, substreamCount); BuilderSparseStreamExtent dataExtent = new BuilderSparseStreamExtent(fileEnd, dataSubStream); extents.Add(dataExtent); fileEnd += range.Count * _blockSize; } totalLength = fileEnd; return extents; }
internal override List <BuilderExtent> FixExtents(out long totalLength) { if (_diskType != DiskType.Dynamic) { throw new NotSupportedException("Creation of only dynamic disks currently implemented"); } List <BuilderExtent> extents = new List <BuilderExtent>(); int logicalSectorSize = 512; int physicalSectorSize = 4096; long chunkRatio = (0x800000L * logicalSectorSize) / _blockSize; long dataBlocksCount = Utilities.Ceil(_content.Length, _blockSize); long sectorBitmapBlocksCount = Utilities.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 = fileEnd; batRegion.Length = (uint)Utilities.RoundUp(totalBatEntriesDynamic * 8, Sizes.OneMiB); batRegion.Flags = RegionFlags.Required; regionTable.Regions.Add(batRegion.Guid, batRegion); fileEnd += batRegion.Length; extents.Add(ExtentForStruct(fileHeader, 0)); extents.Add(ExtentForStruct(header1, 64 * Sizes.OneKiB)); extents.Add(ExtentForStruct(header2, 128 * Sizes.OneKiB)); extents.Add(ExtentForStruct(regionTable, 192 * Sizes.OneKiB)); extents.Add(ExtentForStruct(regionTable, 256 * Sizes.OneKiB)); // Metadata FileParameters fileParams = new FileParameters() { BlockSize = (uint)_blockSize, Flags = FileParametersFlags.None }; ParentLocator parentLocator = new ParentLocator(); byte[] metadataBuffer = new byte[metadataRegion.Length]; MemoryStream metadataStream = new MemoryStream(metadataBuffer); Metadata.Initialize(metadataStream, fileParams, (ulong)_content.Length, (uint)logicalSectorSize, (uint)physicalSectorSize, null); extents.Add(new BuilderBufferExtent(metadataRegion.FileOffset, metadataBuffer)); List <Range <long, long> > presentBlocks = new List <Range <long, long> >(StreamExtent.Blocks(_content.Extents, _blockSize)); // BAT BlockAllocationTableBuilderExtent batExtent = new BlockAllocationTableBuilderExtent(batRegion.FileOffset, batRegion.Length, presentBlocks, fileEnd, _blockSize, chunkRatio); extents.Add(batExtent); // Stream contents foreach (var range in presentBlocks) { long substreamStart = range.Offset * _blockSize; long substreamCount = Math.Min(_content.Length - substreamStart, range.Count * _blockSize); SubStream dataSubStream = new SubStream(_content, substreamStart, substreamCount); BuilderSparseStreamExtent dataExtent = new BuilderSparseStreamExtent(fileEnd, dataSubStream); extents.Add(dataExtent); fileEnd += range.Count * _blockSize; } totalLength = fileEnd; return(extents); }