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));
 }
Exemple #2
0
 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;
                }
            }
        }
Exemple #5
0
        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)