public static DiskImage Create(DiskImage hdd, long offset, long size) { while (hdd is OffsetDiskImage) { var off = (OffsetDiskImage)hdd; offset += off.mOffset; hdd = off.mHdd; } return(new OffsetDiskImage(hdd, offset, size)); }
protected OffsetTableDiskImage(DiskImage hdd) { if (hdd == null) { throw new ArgumentNullException(nameof(hdd)); } mHdd = hdd; mReadBlock = readBlock; mGetBlockKey = getBlockKey; }
protected void Init(DiskImage hdd, long offset, long size) { if (offset < 0) { throw new ArgumentOutOfRangeException(); } if (offset + size > hdd.Length) { throw new ArgumentOutOfRangeException(); } mHdd = hdd; mOffset = offset; mSize = size; }
unsafe public VdiDiskImage(DiskImage hdd) : base(hdd) { var headBytes = hdd.ReadBytes(0, sizeof(VdiHeader)); VdiHeader head = Program.ToStruct <VdiHeader>(headBytes); if (head.ImageSig != VdiMagic) { throw new Exception("Wrong magic."); } if (head.Version != VdiVersion) { throw new Exception("Wrong version."); } if (head.SizeOfHeader != VdiHeadSize) { throw new Exception("Wrong size."); } if (head.ImageType != ImageType.Dynamic) { throw new NotImplementedException("Only dynamic is supported."); } var dataOffset = head.OffsetData; mBlockOffsets = new long[head.BlocksInHdd]; mBlockSize = (int)head.BlockSize; for (long i = 0; i < head.BlocksInHdd; i++) { uint blockLoc; hdd.Get <uint>(head.OffsetBlocks + i * 4, out blockLoc); if (blockLoc == ~0u) { mBlockOffsets[i] = -1; } else { mBlockOffsets[i] = dataOffset + blockLoc * mBlockSize; } } }
public VhdxDiskImage(DiskImage hdd) : base(hdd) { VHDX_REGION_TABLE_ENTRY batRegion, metadataRegion; GetRegions(out batRegion, out metadataRegion); VHDX_FILE_PARAMETERS fileParams; uint logicalSectorSize; ReadMetadata(metadataRegion, out fileParams, out mVirtualDiskSize, out logicalSectorSize); //TODO: confirm that we should use the logical, not the physica sector size. if (logicalSectorSize != Program.SECTOR_SIZE) { //TODO: support other sizes. throw new Exception("Unsupported sector size."); } if (fileParams.HasParent) { throw new NotImplementedException("Differencing disk are not supported."); } //check all these calculations to make sure our assumptions about data sizes are correct checked { mBlockSize = (int)fileParams.BlockSize; int chunkRatio = (int)((1L << 23) * logicalSectorSize / mBlockSize); int dataBlockCount = (int)Math.Ceiling((decimal)mVirtualDiskSize / mBlockSize); int sectorBitmapCount = (int)Math.Ceiling((decimal)dataBlockCount / chunkRatio); int totalBatEntries = dataBlockCount + (int)Math.Floor((dataBlockCount - 1) / (decimal)chunkRatio); if (batRegion.Length < Program.SizeOf <VHDX_BAT_ENTRY>() * totalBatEntries) { throw new Exception("Bat region is not big enough to contain all the bat entries!"); } var batBytes = mHdd.ReadBytes((long)batRegion.FileOffset, (int)batRegion.Length); mBlockOffsets = new long[dataBlockCount]; int fileOffsetsNdx = 0; for (int i = 0; i < totalBatEntries; i++) { var isSectorBitmap = i % (chunkRatio + 1) == chunkRatio; var entry = Program.ToStruct <VHDX_BAT_ENTRY>(batBytes, i * Program.SizeOf <VHDX_BAT_ENTRY>()); if (isSectorBitmap) { if (entry.SectorBitmapState != SectorBitmapState.NotPresent) { throw new Exception("Present bat entry!"); } } else { long offset; switch (entry.PayloadState) { case PayloadBlockState.NotPresent: case PayloadBlockState.Undefined: case PayloadBlockState.BlockZero: case PayloadBlockState.Unmapped: offset = 0; break; case PayloadBlockState.FullyPresent: offset = entry.FileOffsetMB << 20; break; case PayloadBlockState.PartiallyPresent: throw new NotSupportedException("Partially present blocks are not supported."); default: throw new Exception($"Unknown BAT entry state: {entry.PayloadState}"); } if (offset == 0) { offset = -1; } mBlockOffsets[fileOffsetsNdx++] = offset; } } } }
private OffsetDiskImage(DiskImage hdd, long offset, long size) { Init(hdd, offset, size); }
public FixedVhd(DiskImage hdd, in VhdHeader head)