public unsafe VdiHardDisk(HardDisk 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 static HardDisk Create(HardDisk hdd) { byte[] headBytes = hdd.ReadBytes(hdd.Length - 512, 512); VhdHeader head = Program.ToStructFromBigEndian <VhdHeader>(headBytes); if (head.CookieStr != "conectix") { throw new Exception("missing magic string"); } if (head.FileFormatVersion != 0x00010000) { throw new Exception("upsupported version"); } //TODO: validate checksum if (head.DiskType == DiskType.Fixed) { return(new FixedVhd(hdd, in head)); } else if (head.DiskType == DiskType.Dynamic) { return(new DynamicVhd(hdd, in head)); } else { throw new Exception("Only fixed size VHDs are supported."); } }
unsafe public VdiHardDisk(HardDisk 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 override void ReadBytes(Span <byte> dest, long offset) { CheckOffsets(offset, dest.Length); mHdd.ReadBytes(dest, mOffset + offset); }
protected override void ReadBytesCore(Span <byte> dest, long offset) { mHdd.ReadBytes(dest, offset); }
static VhdHeader GetHeader(HardDisk hdd) { return Program.ToStructByteSwap<VhdHeader>(hdd.ReadBytes(hdd.Length - 512, 512)); }
public DynamicVhd(HardDisk hdd) : base(hdd) { VhdHeader head = GetHeader(hdd); int dySize = Program.SizeOf<DynamicHeader>(); DynamicHeader dyhead = Program.ToStructByteSwap<DynamicHeader>(hdd.ReadBytes(head.DataOffset, dySize)); if (dyhead.CookieStr != "cxsparse") throw new Exception("missing magic string"); if (dyhead.HeaderVersion != 0x00010000) throw new NotSupportedException("wrong version"); if (dyhead.ParentUniqueID != Guid.Empty) throw new NotSupportedException("Differencing disks not supported."); mSize = head.CurrentSize; mBlockSize = dyhead.BlockSize; int sectorBitmapSize = (mBlockSize / SECTOR_SIZE) / 8; int numberOfBlocks = (int)(mSize / mBlockSize); if (numberOfBlocks > dyhead.MaxTableEntries) throw new Exception(); mBlockOffsets = new long[numberOfBlocks]; var bat = hdd.ReadBytes(dyhead.TableOffset, numberOfBlocks * 4); for (int i = 0; i < numberOfBlocks; i++) { Program.ByteSwap(typeof(int), bat, i * 4); long batEntry = Program.ToStruct<int>(bat, i * 4); if (batEntry != -1) { batEntry *= SECTOR_SIZE; //skip the sector bitmap, since we don't support differencing disks batEntry += sectorBitmapSize; } mBlockOffsets[i] = batEntry; } }