Skip to content

Commit

Permalink
Fix switching transacted streams
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-visionaid committed Dec 5, 2024
1 parent fb281a4 commit dbdef88
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 14 deletions.
33 changes: 33 additions & 0 deletions OpenMcdf.Tests/RootStorageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,37 @@ public void SwitchFile(Version version, int subStorageCount)
try { File.Delete(fileName); } catch { }
}
}

[TestMethod]
[DataRow(Version.V3, 0)]
[DataRow(Version.V3, 1)]
[DataRow(Version.V3, 2)]
[DataRow(Version.V3, 4)] // Required 2 sectors including root
[DataRow(Version.V4, 0)]
[DataRow(Version.V4, 1)]
[DataRow(Version.V4, 2)]
[DataRow(Version.V4, 32)] // Required 2 sectors including root
public void SwitchTransactedStream(Version version, int subStorageCount)
{
using MemoryStream originalMemoryStream = new();
using MemoryStream switchedMemoryStream = new();

using (var rootStorage = RootStorage.Create(originalMemoryStream, version, StorageModeFlags.Transacted | StorageModeFlags.LeaveOpen))
{
for (int i = 0; i < subStorageCount; i++)
rootStorage.CreateStorage($"Test{i}");

rootStorage.SwitchTo(switchedMemoryStream);
rootStorage.Commit();
}

using (var rootStorage = RootStorage.Open(switchedMemoryStream))
{
IEnumerable<EntryInfo> entries = rootStorage.EnumerateEntries();
Assert.AreEqual(subStorageCount, entries.Count());

for (int i = 0; i < subStorageCount; i++)
rootStorage.OpenStorage($"Test{i}");
}
}
}
13 changes: 9 additions & 4 deletions OpenMcdf/RootContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ internal sealed class RootContext : ContextBase, IDisposable

public Stream BaseStream { get; }

public Stream Stream { get; }

public CfbBinaryReader Reader { get; }

public CfbBinaryWriter Writer
Expand Down Expand Up @@ -104,17 +106,20 @@ public RootContext(RootContextSite rootContextSite, Stream stream, Version versi
DirectoryEntriesPerSector = SectorSize / DirectoryEntry.Length;
Length = stream.Length;

Stream actualStream = stream;
if (contextFlags.HasFlag(IOContextFlags.Transacted))
{
Stream overlayStream = stream is MemoryStream ? new MemoryStream() : File.Create(Path.GetTempFileName());
transactedStream = new TransactedStream(ContextSite, stream, overlayStream);
actualStream = new BufferedStream(transactedStream, SectorSize);
Stream = new BufferedStream(transactedStream, SectorSize);
}
else
{
Stream = stream;
}

Reader = new(actualStream);
Reader = new(Stream);
if (stream.CanWrite)
writer = new(actualStream);
writer = new(Stream);

Fat = new(ContextSite);
DirectoryEntries = new(ContextSite);
Expand Down
12 changes: 2 additions & 10 deletions OpenMcdf/RootStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public static RootStorage Create(Stream stream, Version version = Version.V3, St
return new RootStorage(rootContextSite, flags);
}

public static RootStorage CreateInMemory(Version version = Version.V3) => Create(new MemoryStream(), version);
public static RootStorage CreateInMemory(Version version = Version.V3, StorageModeFlags flags = StorageModeFlags.None) => Create(new MemoryStream(), version, flags);

public static RootStorage Open(string fileName, FileMode mode, StorageModeFlags flags = StorageModeFlags.None)
{
Expand Down Expand Up @@ -205,15 +205,7 @@ public void Revert()
private void SwitchToCore(Stream stream, bool allowLeaveOpen)
{
Flush();

stream.SetLength(Context.BaseStream.Length);

stream.Position = 0;
Context.BaseStream.Position = 0;

Context.BaseStream.CopyTo(stream);
stream.Position = 0;

Context.Stream.CopyAllTo(stream);
Context.Dispose();

IOContextFlags contextFlags = ToIOContextFlags(storageModeFlags);
Expand Down

0 comments on commit dbdef88

Please sign in to comment.