示例#1
0
        private void WriteHeader()
        {
            long otherPos;

            _header.SequenceNumber++;
            _header.CalcChecksum();

            if (_activeHeader == 1)
            {
                _fileStream.Position = 128 * Sizes.OneKiB;
                otherPos             = 64 * Sizes.OneKiB;
            }
            else
            {
                _fileStream.Position = 64 * Sizes.OneKiB;
                otherPos             = 128 * Sizes.OneKiB;
            }

            StreamUtilities.WriteStruct(_fileStream, _header);
            _fileStream.Flush();

            _header.SequenceNumber++;
            _header.CalcChecksum();

            _fileStream.Position = otherPos;
            StreamUtilities.WriteStruct(_fileStream, _header);
            _fileStream.Flush();
        }
        internal static Metadata Initialize(Stream metadataStream, FileParameters fileParameters, ulong diskSize,
                                            uint logicalSectorSize, uint physicalSectorSize, ParentLocator parentLocator)
        {
            MetadataTable header = new MetadataTable();

            uint dataOffset = (uint)(64 * Sizes.OneKiB);

            dataOffset += AddEntryStruct(fileParameters, MetadataTable.FileParametersGuid, MetadataEntryFlags.IsRequired,
                                         header, dataOffset, metadataStream);
            dataOffset += AddEntryValue(diskSize, EndianUtilities.WriteBytesLittleEndian, MetadataTable.VirtualDiskSizeGuid,
                                        MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream);
            dataOffset += AddEntryValue(Guid.NewGuid(), EndianUtilities.WriteBytesLittleEndian, MetadataTable.Page83DataGuid,
                                        MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream);
            dataOffset += AddEntryValue(logicalSectorSize, EndianUtilities.WriteBytesLittleEndian,
                                        MetadataTable.LogicalSectorSizeGuid, MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk,
                                        header, dataOffset, metadataStream);
            dataOffset += AddEntryValue(physicalSectorSize, EndianUtilities.WriteBytesLittleEndian,
                                        MetadataTable.PhysicalSectorSizeGuid, MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk,
                                        header, dataOffset, metadataStream);
            if (parentLocator != null)
            {
                dataOffset += AddEntryStruct(parentLocator, MetadataTable.ParentLocatorGuid,
                                             MetadataEntryFlags.IsRequired, header, dataOffset, metadataStream);
            }

            metadataStream.Position = 0;
            StreamUtilities.WriteStruct(metadataStream, header);
            return(new Metadata(metadataStream));
        }
        private static uint AddEntryStruct <T>(T data, Guid id, MetadataEntryFlags flags, MetadataTable header,
                                               uint dataOffset, Stream stream)
            where T : IByteArraySerializable
        {
            MetadataEntryKey key   = new MetadataEntryKey(id, (flags & MetadataEntryFlags.IsUser) != 0);
            MetadataEntry    entry = new MetadataEntry();

            entry.ItemId = id;
            entry.Offset = dataOffset;
            entry.Length = (uint)data.Size;
            entry.Flags  = flags;

            header.Entries[key] = entry;

            stream.Position = dataOffset;
            StreamUtilities.WriteStruct(stream, data);

            return(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(nameof(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         = MathUtilities.Ceil(capacity, blockSize);
            long sectorBitmapBlocksCount = MathUtilities.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)MathUtilities.RoundUp(totalBatEntriesDynamic * 8, Sizes.OneMiB);
            batRegion.Flags      = RegionFlags.Required;
            regionTable.Regions.Add(batRegion.Guid, batRegion);

            fileEnd += batRegion.Length;

            stream.Position = 0;
            StreamUtilities.WriteStruct(stream, fileHeader);

            stream.Position = 64 * Sizes.OneKiB;
            StreamUtilities.WriteStruct(stream, header1);

            stream.Position = 128 * Sizes.OneKiB;
            StreamUtilities.WriteStruct(stream, header2);

            stream.Position = 192 * Sizes.OneKiB;
            StreamUtilities.WriteStruct(stream, regionTable);

            stream.Position = 256 * Sizes.OneKiB;
            StreamUtilities.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);
        }