Пример #1
0
 internal DiskImageFileInfo(FileHeader fileHeader, VhdxHeader vhdxHeader1, VhdxHeader vhdxHeader2, RegionTable regions, Metadata metadata, LogSequence activeLogSequence)
 {
     _fileHeader        = fileHeader;
     _vhdxHeader1       = vhdxHeader1;
     _vhdxHeader2       = vhdxHeader2;
     _regions           = regions;
     _metadata          = metadata;
     _activeLogSequence = activeLogSequence;
 }
Пример #2
0
 internal DiskImageFileInfo(FileHeader fileHeader, VhdxHeader vhdxHeader1, VhdxHeader vhdxHeader2, RegionTable regions, Metadata metadata, LogSequence activeLogSequence)
 {
     _fileHeader = fileHeader;
     _vhdxHeader1 = vhdxHeader1;
     _vhdxHeader2 = vhdxHeader2;
     _regions = regions;
     _metadata = metadata;
     _activeLogSequence = activeLogSequence;
 }
Пример #3
0
        private void ReadRegionTable()
        {
            _fileStream.Position = 192 * Sizes.OneKiB;
            _regionTable         = Utilities.ReadStruct <RegionTable>(_fileStream);
            foreach (var entry in _regionTable.Regions.Values)
            {
                if ((entry.Flags & RegionFlags.Required) != 0)
                {
                    if (entry.Guid != RegionTable.BatGuid && entry.Guid != RegionTable.MetadataRegionGuid)
                    {
                        throw new IOException("Invalid VHDX file - unrecognised required region");
                    }
                }

                _freeSpace.Reserve(entry.FileOffset, entry.Length);
            }
        }
Пример #4
0
        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);
        }
Пример #5
0
 internal RegionTableInfo(RegionTable table)
 {
     _table = table;
 }
        private void ReadRegionTable()
        {
            _fileStream.Position = 192 * Sizes.OneKiB;
            _regionTable = Utilities.ReadStruct<RegionTable>(_fileStream);
            foreach (var entry in _regionTable.Regions.Values)
            {
                if ((entry.Flags & RegionFlags.Required) != 0)
                {
                    if (entry.Guid != RegionTable.BatGuid && entry.Guid != RegionTable.MetadataRegionGuid)
                    {
                        throw new IOException("Invalid VHDX file - unrecognised required region");
                    }
                }

                _freeSpace.Reserve(entry.FileOffset, entry.Length);
            }
        }
Пример #7
0
        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);
        }
Пример #8
0
            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;
            }
Пример #9
0
            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);
            }