private void Initialize()
        {
            _fileStream.Position = 0;
            FileHeader fileHeader = Utilities.ReadStruct <FileHeader>(_fileStream);

            if (!fileHeader.IsValid)
            {
                throw new IOException("Invalid VHDX file - file signature mismatch");
            }

            _freeSpace = new FreeSpaceTable(_fileStream.Length);

            ReadHeaders();

            if (_header.LogGuid != Guid.Empty)
            {
                throw new NotSupportedException("Detected VHDX file with replay log - not yet supported");
            }

            _freeSpace.Reserve((long)_header.LogOffset, _header.LogLength);

            ReadRegionTable();

            ReadMetadata();

            _batStream = OpenRegion(RegionTable.BatGuid);
            _freeSpace.Reserve(BatControlledFileExtents());

            // Indicate the file is open for modification
            if (_fileStream.CanWrite)
            {
                _header.FileWriteGuid = Guid.NewGuid();
                WriteHeader();
            }
        }
Example #2
0
        private void ReplayLog()
        {
            _freeSpace.Reserve((long)_header.LogOffset, _header.LogLength);

            _logicalStream = _fileStream;

            // If log is empty, skip.
            if (_header.LogGuid == Guid.Empty)
            {
                return;
            }

            LogSequence activeLogSequence = FindActiveLogSequence();

            if (activeLogSequence == null || activeLogSequence.Count == 0)
            {
                throw new IOException("Unable to replay VHDX log, suspected corrupt VHDX file");
            }

            if (activeLogSequence.Head.FlushedFileOffset > (ulong)_logicalStream.Length)
            {
                throw new IOException("truncated VHDX file found while replaying log");
            }

            if (activeLogSequence.Count > 1 || !activeLogSequence.Head.IsEmpty)
            {
                // However, have seen VHDX with a non-empty log with no data to replay.  These are
                // 'safe' to open.
                if (!_fileStream.CanWrite)
                {
                    SnapshotStream replayStream = new SnapshotStream(_fileStream, Ownership.None);
                    replayStream.Snapshot();
                    _logicalStream = replayStream;
                }
                foreach (LogEntry logEntry in activeLogSequence)
                {
                    if (logEntry.LogGuid != _header.LogGuid)
                    {
                        throw new IOException("Invalid log entry in VHDX log, suspected currupt VHDX file");
                    }
                    if (logEntry.IsEmpty)
                    {
                        continue;
                    }
                    logEntry.Replay(_logicalStream);
                }
                _logicalStream.Seek((long)activeLogSequence.Head.LastFileOffset, SeekOrigin.Begin);
            }
        }
Example #3
0
        private void Initialize()
        {
            _fileStream.Position = 0;
            FileHeader fileHeader = StreamUtilities.ReadStruct <FileHeader>(_fileStream);

            if (!fileHeader.IsValid)
            {
                throw new IOException("Invalid VHDX file - file signature mismatch");
            }

            _freeSpace = new FreeSpaceTable(_fileStream.Length);

            ReadHeaders();

            ReplayLog();

            ReadRegionTable();

            ReadMetadata();

            _batStream = OpenRegion(RegionTable.BatGuid);
            _freeSpace.Reserve(BatControlledFileExtents());

            // Indicate the file is open for modification
            if (_fileStream.CanWrite)
            {
                _header.FileWriteGuid = Guid.NewGuid();
                WriteHeader();
            }
        }
        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);
            }
        }
Example #5
0
        private void ReplayLog()
        {
            _freeSpace.Reserve((long)_header.LogOffset, _header.LogLength);

            _logicalStream = _fileStream;

            // If log is empty, skip.
            if (_header.LogGuid == Guid.Empty)
            {
                return;
            }

            LogSequence activeLogSequence = FindActiveLogSequence();

            if (activeLogSequence == null || activeLogSequence.Count == 0)
            {
                throw new IOException("Unable to replay VHDX log, suspected corrupt VHDX file");
            }

            if (activeLogSequence.Count > 1 || !activeLogSequence.Head.IsEmpty)
            {
                // TODO - perform actual replay (needs VHDX with real log to replay)
                // However, have seen VHDX with a non-empty log with no data to replay.  These are
                // 'safe' to open.
                throw new NotImplementedException("Actual replay of VHDX logs not implemented yet");

                //// Have a log to replay, and the base stream is read-only. Use a snapshot stream to
                //// replay in RAM.
                ////if (!_fileStream.CanWrite)
                ////{
                ////    SnapshotStream replayStream = new SnapshotStream(_fileStream, Ownership.None);
                ////    replayStream.Snapshot();
                ////    _logicalStream = replayStream;
                ////}
            }
        }
        private void Initialize()
        {
            _fileStream.Position = 0;
            FileHeader fileHeader = Utilities.ReadStruct<FileHeader>(_fileStream);
            if (!fileHeader.IsValid)
            {
                throw new IOException("Invalid VHDX file - file signature mismatch");
            }

            _freeSpace = new FreeSpaceTable(_fileStream.Length);

            ReadHeaders();

            if (_header.LogGuid != Guid.Empty)
            {
                throw new NotSupportedException("Detected VHDX file with replay log - not yet supported");
            }

            _freeSpace.Reserve((long)_header.LogOffset, _header.LogLength);

            ReadRegionTable();

            ReadMetadata();

            _batStream = OpenRegion(RegionTable.BatGuid);
            _freeSpace.Reserve(BatControlledFileExtents());

            // Indicate the file is open for modification
            if (_fileStream.CanWrite)
            {
                _header.FileWriteGuid = Guid.NewGuid();
                WriteHeader();
            }
        }