Beispiel #1
0
        public void BuildStreamLengthIsRespected()
        {
            int length = 1024;
            var extent = new BuilderSparseStreamExtent(0, new ZeroStream(2 * length));

            using (var stream = new BuiltStream(length, new List <BuilderExtent> {
                extent
            }))
            {
                Assert.Equal(0, stream.Position);
                Assert.Equal(length, stream.Length);
                var content = new byte[2 * length];
                var read    = stream.Read(content, 0, content.Length);
                Assert.Equal(length, read);
                Assert.Equal(stream.Length, stream.Position);
            }
        }
 /// <summary>
 /// Sets a stream representing the content of a partition in the partition table.
 /// </summary>
 /// <param name="index">The index of the partition</param>
 /// <param name="stream">The stream with the contents of the partition</param>
 public void SetPartitionContent(int index, SparseStream stream)
 {
     _partitionContents[index] = new BuilderSparseStreamExtent(_partitionTable[index].FirstSector * Sizes.Sector, stream);
 }
 /// <summary>
 /// Sets a stream representing the content of a partition in the partition table.
 /// </summary>
 /// <param name="index">The index of the partition</param>
 /// <param name="stream">The stream with the contents of the partition</param>
 public void SetPartitionContent(int index, SparseStream stream)
 {
     _partitionContents[index] = new BuilderSparseStreamExtent(_partitionTable[index].FirstSector * Sizes.Sector, stream);
 }
Beispiel #4
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;
            }
Beispiel #5
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);
            }