Skip to content

Commit

Permalink
Improve argument/state validation
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-visionaid committed Nov 21, 2024
1 parent e4567ed commit 5c35810
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 18 deletions.
16 changes: 14 additions & 2 deletions OpenMcdf.Tests/RootStorageTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,27 @@ public sealed class RootStorageTests
{
[TestMethod]
[DoNotParallelize] // Test sharing
[DataRow("MultipleStorage.cfs")]
[DataRow("TestStream_v3_0.cfs")]
public void Open(string fileName)
{
using var rootStorage = RootStorage.OpenRead(fileName);
using var rootStorage2 = RootStorage.OpenRead(fileName);

Assert.ThrowsException<IOException>(() => RootStorage.Open(fileName, FileMode.Open));
Assert.ThrowsException<IOException>(() => RootStorage.Open(fileName, FileMode.Open, FileAccess.ReadWrite));
Assert.ThrowsException<IOException>(() => RootStorage.OpenWrite(fileName));

using CfbStream stream = rootStorage.OpenStream("TestStream");
Assert.ThrowsException<NotSupportedException>(() => stream.WriteByte(0));

Assert.ThrowsException<NotSupportedException>(() => rootStorage.CreateStream("TestStream2"));
Assert.ThrowsException<NotSupportedException>(() => rootStorage.CreateStorage("TestStream2"));
Assert.ThrowsException<NotSupportedException>(() => rootStorage.Delete("TestStream"));
Assert.ThrowsException<NotSupportedException>(() => rootStorage.Commit());
Assert.ThrowsException<NotSupportedException>(() => rootStorage.Revert());
Assert.ThrowsException<NotSupportedException>(() => rootStorage.CreationTime = DateTime.MinValue);
Assert.ThrowsException<NotSupportedException>(() => rootStorage.ModifiedTime = DateTime.MinValue);
Assert.ThrowsException<NotSupportedException>(() => rootStorage.CLISD = Guid.Empty);
Assert.ThrowsException<NotSupportedException>(() => rootStorage.StateBits = 0);
}

[TestMethod]
Expand Down
2 changes: 1 addition & 1 deletion OpenMcdf.Tests/StreamTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public void OpenStream(string fileName)

Assert.ThrowsException<FileNotFoundException>(() => rootStorage.OpenStream(""));

CfbStream stream = rootStorage.OpenStream("TestStream");
using CfbStream stream = rootStorage.OpenStream("TestStream");
Assert.AreEqual("TestStream", stream.EntryInfo.Name);
}

Expand Down
25 changes: 20 additions & 5 deletions OpenMcdf/RootContext.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace OpenMcdf;
using System.Diagnostics.CodeAnalysis;

namespace OpenMcdf;

enum IOContextFlags
{
Expand Down Expand Up @@ -152,6 +154,20 @@ public void Dispose()
}
}

[MemberNotNull(nameof(writer))]
public void ThrowIfNotWritable()
{
if (writer is null)
throw new NotSupportedException("Root storage is not writable.");
}

[MemberNotNull(nameof(transactedStream))]
public void ThrowIfNotTransacted()
{
if (transactedStream is null)
throw new NotSupportedException("Cannot commit non-transacted storage.");
}

public void Flush()
{
Fat.Flush();
Expand Down Expand Up @@ -181,8 +197,8 @@ public void WriteHeader()

public void Commit()
{
if (writer is null || transactedStream is null)
throw new InvalidOperationException("Cannot commit non-transacted storage.");
ThrowIfNotWritable();
ThrowIfNotTransacted();

miniStream?.Flush();
miniFat?.Flush();
Expand All @@ -194,8 +210,7 @@ public void Commit()

public void Revert()
{
if (writer is null || transactedStream is null)
throw new InvalidOperationException("Cannot revert non-transacted storage.");
ThrowIfNotTransacted();

transactedStream.Revert();
}
Expand Down
23 changes: 15 additions & 8 deletions OpenMcdf/RootStorage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@ public sealed class RootStorage : Storage, IDisposable
{
readonly StorageModeFlags storageModeFlags;

private static void ThrowIfInvalid(FileMode mode)
{
if (mode is FileMode.Append)
throw new ArgumentException("Append mode is not valid for compound files.", nameof(mode));
}

private static void ThrowIfInvalid(FileAccess access)
{
if (access is FileAccess.Write)
throw new ArgumentException("Write-only access is not valid for compound files.", nameof(access));
}

private static void ThrowIfLeaveOpen(StorageModeFlags flags)
{
if (flags.HasFlag(StorageModeFlags.LeaveOpen))
Expand Down Expand Up @@ -64,6 +76,7 @@ public static RootStorage Create(Stream stream, Version version = Version.V3, St

public static RootStorage Open(string fileName, FileMode mode, StorageModeFlags flags = StorageModeFlags.None)
{
ThrowIfInvalid(mode);
ThrowIfLeaveOpen(flags);

FileStream stream = File.Open(fileName, mode);
Expand All @@ -72,6 +85,8 @@ public static RootStorage Open(string fileName, FileMode mode, StorageModeFlags

public static RootStorage Open(string fileName, FileMode mode, FileAccess access, StorageModeFlags flags = StorageModeFlags.None)
{
ThrowIfInvalid(mode);
ThrowIfInvalid(access);
ThrowIfLeaveOpen(flags);

FileStream stream = File.Open(fileName, mode, access);
Expand All @@ -97,14 +112,6 @@ public static RootStorage OpenRead(string fileName, StorageModeFlags flags = Sto
return Open(stream, flags);
}

public static RootStorage OpenWrite(string fileName, StorageModeFlags flags = StorageModeFlags.None)
{
ThrowIfLeaveOpen(flags);

FileStream stream = File.OpenWrite(fileName);
return Open(stream, flags);
}

RootStorage(RootContextSite rootContextSite, StorageModeFlags storageModeFlags)
: base(rootContextSite, rootContextSite.Context.RootEntry, null)
{
Expand Down
11 changes: 11 additions & 0 deletions OpenMcdf/Storage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public Guid CLISD
get => directoryEntry.CLSID;
set
{
Context.ThrowIfNotWritable();

directoryEntry.CLSID = value;
Context.DirectoryEntries.Write(directoryEntry);
}
Expand All @@ -42,6 +44,8 @@ public DateTime CreationTime
get => directoryEntry.CreationTime;
set
{
Context.ThrowIfNotWritable();

directoryEntry.CreationTime = value;
Context.DirectoryEntries.Write(directoryEntry);
}
Expand All @@ -52,6 +56,8 @@ public DateTime ModifiedTime
get => directoryEntry.ModifiedTime;
set
{
Context.ThrowIfNotWritable();

directoryEntry.ModifiedTime = value;
Context.DirectoryEntries.Write(directoryEntry);
}
Expand All @@ -62,6 +68,8 @@ public uint StateBits
get => directoryEntry.StateBits;
set
{
Context.ThrowIfNotWritable();

directoryEntry.StateBits = value;
Context.DirectoryEntries.Write(directoryEntry);
}
Expand Down Expand Up @@ -125,6 +133,7 @@ public Storage CreateStorage(string name)
ThrowHelper.ThrowIfNameIsInvalid(name);

this.ThrowIfDisposed(Context.IsDisposed);
Context.ThrowIfNotWritable();

DirectoryEntry entry = AddDirectoryEntry(StorageType.Storage, name);
return new Storage(ContextSite, entry, this);
Expand All @@ -135,6 +144,7 @@ public CfbStream CreateStream(string name)
ThrowHelper.ThrowIfNameIsInvalid(name);

this.ThrowIfDisposed(Context.IsDisposed);
Context.ThrowIfNotWritable();

DirectoryEntry entry = AddDirectoryEntry(StorageType.Stream, name);
return new CfbStream(ContextSite, entry, this);
Expand Down Expand Up @@ -207,6 +217,7 @@ public void Delete(string name)
ThrowHelper.ThrowIfNameIsInvalid(name);

this.ThrowIfDisposed(Context.IsDisposed);
Context.ThrowIfNotWritable();

directoryTree.TryGetDirectoryEntry(name, out DirectoryEntry? entry);
if (entry is null)
Expand Down
4 changes: 3 additions & 1 deletion OpenMcdf/StreamExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ public static int ReadByteCore(this Stream stream)

public static void WriteByteCore(this Stream stream, byte value)
{
ReadOnlySpan<byte> bytes = stackalloc byte[] { value };
stream.ThrowIfNotWritable();

ReadOnlySpan<byte> bytes = [value];
stream.Write(bytes);
}

Expand Down
2 changes: 1 addition & 1 deletion StructuredStorageExplorer/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ private void LoadFile(string fileName)
cf = null;

// Load file
cf = RootStorage.OpenWrite(fileName);
cf = RootStorage.Open(fileName, FileMode.Open);

fileNameLabel.Text = fileName;
saveAsToolStripMenuItem.Enabled = true;
Expand Down

0 comments on commit 5c35810

Please sign in to comment.