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(); } }
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); } }
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); } }
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(); } }