-
-
Notifications
You must be signed in to change notification settings - Fork 32
Description
I stumbled upon an exception while creating a lot of single files using FatFileSystem where I create a new FatFileSystem instance for each file and managed to create following test to reproduce the issue:
[Fact]
public async Task CreateFilesInSubdirectoryUsingFatFileSystemPerFile()
{
using var diskStream = new SparseMemoryStream();
diskStream.Position = 0;
using (var fsFormat = FatFileSystem.FormatFloppy(diskStream, FloppyDiskType.HighDensity, "FLOPPY_IMG "))
{
fsFormat.CreateDirectory("dir");
}
for (var i = 0; i < 20; i++)
{
using (var fsCreate = new FatFileSystem(diskStream))
{
using (var fileStream = fsCreate.OpenFile($"dir{Path.DirectorySeparatorChar}file{i}.txt", FileMode.Create))
{
await fileStream.WriteAsync(new byte[10]);
}
}
}
using var fsAssert = new FatFileSystem(diskStream);
{
var entries = fsAssert.GetFileSystemEntries("").ToList();
Assert.Single(entries);
Assert.Equal("dir", entries[0]);
entries = fsAssert.GetFileSystemEntries("dir").ToList();
Assert.Equal(20, entries.Count);
Assert.Equal(Enumerable.Range(0, 20).Select(i => $"dir\\file{i}.txt"), entries);
}
}
From what I have managed to investigate so far, the issue seems related to ClusterStream.cs switching from one cluster to another when the cluster for dir is full (512 bytes) causing the position (pos) going from 512 to 0. The exception is then thrown by AddEntryRaw method adding the entry to _entries dictionary in Directory.cs and 0 already exists from an entry in previous cluster.
I would like to help with a fix for the issue, but I would also ask some advise. The _entries dictionary uses cluster position as key to index entries and must be changed to something else than ClusterStream position. I initially thought about using Guid's instead of long's as dictionary key, but then I realised the long key fromthe dictionary is also used to seek to entry positions when deleting entries. Here I'm not sure how seeking to position of entry to delete works when the cluster have changed within the ClusterStream. More investigation needed