Пример #1
0
        /// <summary>
        /// Gets the locations of the parent file.
        /// </summary>
        /// <param name="fileLocator">The file locator to use.</param>
        /// <returns>Array of candidate file locations.</returns>
        private string[] GetParentLocations(FileLocator fileLocator)
        {
            if (!NeedsParent)
            {
                throw new InvalidOperationException("Only differencing disks contain parent locations");
            }

            if (fileLocator == null)
            {
                // Use working directory by default
                fileLocator = new LocalFileLocator(string.Empty);
            }

            List <string> paths = new List <string>();

            ParentLocator locator = _metadata.ParentLocator;
            string        value;

            if (locator.Entries.TryGetValue("relative_path", out value))
            {
                paths.Add(fileLocator.ResolveRelativePath(value));
            }

            if (locator.Entries.TryGetValue("volume_path", out value))
            {
                paths.Add(value);
            }

            if (locator.Entries.TryGetValue("absolute_win32_path", out value))
            {
                paths.Add(value);
            }

            return(paths.ToArray());
        }
Пример #2
0
        public Metadata(Stream regionStream)
        {
            _regionStream          = regionStream;
            _regionStream.Position = 0;
            _table = Utilities.ReadStruct <MetadataTable>(_regionStream);

            _fileParams         = ReadStruct <FileParameters>(MetadataTable.FileParametersGuid, false);
            _diskSize           = ReadValue <ulong>(MetadataTable.VirtualDiskSizeGuid, false, Utilities.ToUInt64LittleEndian);
            _page83Data         = ReadValue <Guid>(MetadataTable.Page83DataGuid, false, Utilities.ToGuidLittleEndian);
            _logicalSectorSize  = ReadValue <uint>(MetadataTable.LogicalSectorSizeGuid, false, Utilities.ToUInt32LittleEndian);
            _physicalSectorSize = ReadValue <uint>(MetadataTable.PhysicalSectorSizeGuid, false, Utilities.ToUInt32LittleEndian);
            _parentLocator      = ReadStruct <ParentLocator>(MetadataTable.ParentLocatorGuid, false);
        }
Пример #3
0
        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, Utilities.WriteBytesLittleEndian, MetadataTable.VirtualDiskSizeGuid,
                                        MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream);
            dataOffset += AddEntryValue(Guid.NewGuid(), Utilities.WriteBytesLittleEndian, MetadataTable.Page83DataGuid,
                                        MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk, header, dataOffset, metadataStream);
            dataOffset += AddEntryValue(logicalSectorSize, Utilities.WriteBytesLittleEndian,
                                        MetadataTable.LogicalSectorSizeGuid, MetadataEntryFlags.IsRequired | MetadataEntryFlags.IsVirtualDisk,
                                        header, dataOffset, metadataStream);
            dataOffset += AddEntryValue(physicalSectorSize, Utilities.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;
            Utilities.WriteStruct(metadataStream, header);
            return(new Metadata(metadataStream));
        }
Пример #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
        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);
        }
Пример #6
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;
            }
Пример #7
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);
            }