diff --git a/Tests/Cosmos.Kernel.Tests.Fat/System.IO/DriveInfoTest.cs b/Tests/Cosmos.Kernel.Tests.Fat/System.IO/DriveInfoTest.cs
new file mode 100644
index 000000000..aedce347f
--- /dev/null
+++ b/Tests/Cosmos.Kernel.Tests.Fat/System.IO/DriveInfoTest.cs
@@ -0,0 +1,136 @@
+using System.IO;
+using Cosmos.TestRunner;
+using Cosmos.Debug.Kernel;
+using System;
+
+namespace Cosmos.Kernel.Tests.Fat.System.IO
+{
+ public class DriveInfoTest
+ {
+ ///
+ /// Tests System.IO.DriveInfo plugs.
+ ///
+ public static void Execute(Debugger mDebugger)
+ {
+ string driveName = @"0:\";
+ var MyDrive = new DriveInfo(driveName);
+
+ mDebugger.Send("START TEST: Get Name");
+
+ Assert.IsTrue(MyDrive.Name == driveName, "DriveInfo.Name failed drive has wrong name");
+
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Get TotalSize");
+ long MyDriveSize = MyDrive.TotalSize;
+
+ mDebugger.Send($"Size is {MyDriveSize}");
+
+ Assert.IsTrue(MyDriveSize > 0, "DriveInfo.TotalSize failed: invalid size");
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Get AvailableFreeSpace");
+ long MyDriveAvailableFreeSpace = MyDrive.AvailableFreeSpace;
+
+ mDebugger.Send($"AvailableFreeSpace {MyDriveAvailableFreeSpace}");
+
+ Assert.IsTrue(MyDriveAvailableFreeSpace >= 0, "DriveInfo.AvailableFreeSpace failed: invalid size");
+
+ Assert.IsFalse(MyDriveAvailableFreeSpace > MyDrive.TotalSize, "DriveInfo.AvailableFreeSpace failed: more than TotalSize");
+
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Get TotalFreeSpace");
+ long MyDriveTotalFreeSpace = MyDrive.TotalFreeSpace;
+
+ mDebugger.Send($"TotalFreeSpace {MyDriveTotalFreeSpace}");
+
+ Assert.IsTrue(MyDriveTotalFreeSpace >= 0, "DriveInfo.TotalFreeSpace failed: invalid size");
+
+ Assert.IsFalse(MyDriveTotalFreeSpace > MyDrive.TotalSize, "DriveInfo.TotalFreeSpace failed: more than TotalSize");
+
+ /*
+ * If disk quotas are enabled AvailableFreeSpace and TotalFreeSpace could be different numbers but TotalFreeSpace
+ * should be always >= of AvailableFreeSpace
+ */
+ Assert.IsTrue(MyDriveTotalFreeSpace >= MyDriveAvailableFreeSpace, "DriveInfo.MyDriveTotalFreeSpace failed: less than AvailableFreeSpace");
+
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Get RootDirectory");
+
+ var xDi = MyDrive.RootDirectory;
+
+ Assert.IsTrue(xDi.Name == MyDrive.Name, "RootDirectory failed");
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Get DriveFormat");
+
+ Assert.IsTrue(MyDrive.DriveFormat == "FAT32", "DriveFormat failed");
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Get VolumeLabel");
+
+ string OriginalVolumeLabel = MyDrive.VolumeLabel;
+
+ mDebugger.Send($"Volume Label of {MyDrive.Name} is {MyDrive.VolumeLabel}");
+
+ Assert.IsTrue(OriginalVolumeLabel == "COSMOS", "VolumeLabel Get failed not the expected value");
+
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Set VolumeLabel to ");
+ // Now try to change it...
+ String NewVolumeLabel = "TEST";
+ mDebugger.Send($"Changing Volume Label to {NewVolumeLabel}...");
+ MyDrive.VolumeLabel = NewVolumeLabel;
+
+ string SetVolumeLabel = MyDrive.VolumeLabel;
+
+ mDebugger.Send($"Volume Label of {MyDrive.Name} is {SetVolumeLabel}");
+
+ Assert.IsTrue(SetVolumeLabel == NewVolumeLabel, "VolumeLabel Set failed: not the expected value");
+
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Set VolumeLabel (restoring original label)");
+ // Now try to change it...
+ mDebugger.Send($"Changing Volume Label to {OriginalVolumeLabel}...");
+ MyDrive.VolumeLabel = OriginalVolumeLabel;
+
+ SetVolumeLabel = MyDrive.VolumeLabel;
+
+ mDebugger.Send($"Volume Label of {MyDrive.Name} is {SetVolumeLabel}");
+
+ Assert.IsTrue(SetVolumeLabel == OriginalVolumeLabel, "VolumeLabel Set failed: not the expected value");
+
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Testing isReady status of the Drive");
+
+ Assert.IsTrue(MyDrive.IsReady, "IsReady failed drive not ready");
+
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Testing DriveType");
+
+ Assert.IsTrue(MyDrive.DriveType == DriveType.Fixed, "DriveType failed drive not of Fixed type");
+
+ mDebugger.Send("END TEST");
+
+ mDebugger.Send("START TEST: Getting all drives info");
+
+ DriveInfo[] xDrives = DriveInfo.GetDrives();
+
+ Assert.IsFalse(xDrives == null, "GetDrives failed: null array returned");
+
+ // I suppose that at least a drive is recognized by Cosmos
+ Assert.IsTrue(xDrives.Length > 0, "GetDrives failed: no drive recognized");
+
+ /* Check that only the Name property of the first one is the same of driveName */
+ Assert.IsTrue(xDrives[0].Name == driveName, "GetDrives failed: first drive is not the same of MyDrive (0:)");
+
+ mDebugger.Send("END TEST");
+ }
+ }
+}
diff --git a/Tests/Cosmos.Kernel.Tests.Fat2/Kernel.cs b/Tests/Cosmos.Kernel.Tests.Fat2/Kernel.cs
index 5a4a2bfac..1e94db18f 100644
--- a/Tests/Cosmos.Kernel.Tests.Fat2/Kernel.cs
+++ b/Tests/Cosmos.Kernel.Tests.Fat2/Kernel.cs
@@ -42,6 +42,7 @@ namespace Cosmos.Kernel.Tests.Fat2
mDebugger.Send("Run");
FileTest.Execute(mDebugger);
+ DriveInfoTest.Execute(mDebugger);
TestController.Completed();
}
diff --git a/source/Cosmos.System2/FileSystem/CosmosVFS.cs b/source/Cosmos.System2/FileSystem/CosmosVFS.cs
index 494035375..76298a200 100644
--- a/source/Cosmos.System2/FileSystem/CosmosVFS.cs
+++ b/source/Cosmos.System2/FileSystem/CosmosVFS.cs
@@ -19,12 +19,9 @@ namespace Cosmos.System.FileSystem
public class CosmosVFS : VFSBase
{
private List mPartitions;
-
-
private List mFileSystems;
-
-
private FileSystem mCurrentFileSystem;
+ private List mRegisteredFileSystems;
///
/// Initializes the virtual file system.
@@ -33,6 +30,9 @@ namespace Cosmos.System.FileSystem
{
mPartitions = new List();
mFileSystems = new List();
+ mRegisteredFileSystems = new List();
+
+ RegisterFileSystem(new FatFileSystemFactory());
InitializePartitions();
if (mPartitions.Count > 0)
@@ -41,6 +41,12 @@ namespace Cosmos.System.FileSystem
}
}
+ public override void RegisterFileSystem(FileSystemFactory aFileSystemFactory)
+ {
+ Global.mFileSystemDebugger.SendInternal($"Registering filesystem {aFileSystemFactory.Name}");
+ mRegisteredFileSystems.Add(aFileSystemFactory);
+ }
+
///
/// Creates a new file.
///
@@ -400,14 +406,15 @@ namespace Cosmos.System.FileSystem
{
string xRootPath = string.Concat(i, VolumeSeparatorChar, DirectorySeparatorChar);
var xSize = (long)(mPartitions[i].BlockCount * mPartitions[i].BlockSize / 1024 / 1024);
- switch (FileSystem.GetFileSystemType(mPartitions[i]))
+
+ // We 'probe' the partition with all the FileSystem registered until we find a Filesystem that can read / write to it
+ foreach (var fs in mRegisteredFileSystems)
{
- case FileSystemType.FAT:
+ if (fs.IsType(mPartitions[i]))
+ {
+ Global.mFileSystemDebugger.SendInternal($"Partion {i} has a {fs.Name} filesystem");
mFileSystems.Add(new FatFileSystem(mPartitions[i], xRootPath, xSize));
- break;
- default:
- global::System.Console.WriteLine("Unknown filesystem type!");
- return;
+ }
}
if ((mFileSystems.Count > 0) && (mFileSystems[mFileSystems.Count - 1].mRootPath == xRootPath))
@@ -547,5 +554,70 @@ namespace Cosmos.System.FileSystem
return aFS.GetRootDirectory();
}
+
+ ///
+ /// Verifies if driveId is a valid id for a drive.
+ ///
+ /// The id of the drive.
+ /// true if the drive id is valid, false otherwise.
+ public override bool IsValidDriveId(string driveId)
+ {
+ Global.mFileSystemDebugger.SendInternal($"driveId is {driveId} after normalization");
+
+ /* We need to remove ':\' to get only the numeric value */
+ driveId = driveId.Remove(driveId.Length - 2);
+ Global.mFileSystemDebugger.SendInternal($"driveId is now {driveId}");
+
+ /*
+ * Cosmos Drive name is really similar to DOS / Windows but a number instead of a letter is used, it is not limited
+ * to 1 character but any number is valid
+ */
+
+ bool isOK = Int32.TryParse(driveId, out int val);
+ Global.mFileSystemDebugger.SendInternal($"isOK is {isOK}");
+
+ return isOK;
+ }
+
+ public override long GetTotalSize(string aDriveId)
+ {
+ var xFs = GetFileSystemFromPath(aDriveId);
+
+ return xFs.mSize;
+ }
+
+ public override long GetAvailableFreeSpace(string aDriveId)
+ {
+ var xFs = GetFileSystemFromPath(aDriveId);
+
+ return xFs.mAvailableFreeSpace;
+ }
+
+ public override long GetTotalFreeSpace(string aDriveId)
+ {
+ var xFs = GetFileSystemFromPath(aDriveId);
+
+ return xFs.mTotalFreeSpace;
+ }
+
+ public override string GetFileSystemType(string aDriveId)
+ {
+ var xFs = GetFileSystemFromPath(aDriveId);
+
+ return xFs.mType;
+ }
+
+ public override string GetFileSystemLabel(string aDriveId)
+ {
+ var xFs = GetFileSystemFromPath(aDriveId);
+
+ return xFs.mLabel;
+ }
+
+ public override void SetFileSystemLabel(string aDriveId, string aLabel)
+ {
+ var xFs = GetFileSystemFromPath(aDriveId);
+ xFs.mLabel = aLabel;
+ }
}
}
diff --git a/source/Cosmos.System2/FileSystem/FAT/FatFileSystem.cs b/source/Cosmos.System2/FileSystem/FAT/FatFileSystem.cs
index 9683fdd5e..fc2e12f79 100644
--- a/source/Cosmos.System2/FileSystem/FAT/FatFileSystem.cs
+++ b/source/Cosmos.System2/FileSystem/FAT/FatFileSystem.cs
@@ -353,6 +353,24 @@ namespace Cosmos.System.FileSystem.FAT
private readonly Fat[] mFats;
+ public override string mType
+ {
+ get
+ {
+ switch (mFatType)
+ {
+ case FatTypeEnum.Fat12:
+ return "FAT12";
+ case FatTypeEnum.Fat16:
+ return "FAT16";
+ case FatTypeEnum.Fat32:
+ return "FAT32";
+ default:
+ throw new Exception("Unknown FAT file system type.");
+ }
+ }
+ }
+
///
/// Initializes a new instance of the class.
///
@@ -587,7 +605,7 @@ namespace Cosmos.System.FileSystem.FAT
}
var result = new List();
- var xEntry = (FatDirectoryEntry)baseDirectory;
+ var xEntry = (FatDiretoryEntry)baseDirectory;
var fatListing = xEntry.ReadDirectoryContents();
for (int i = 0; i < fatListing.Count; i++)
@@ -601,7 +619,7 @@ namespace Cosmos.System.FileSystem.FAT
{
Global.mFileSystemDebugger.SendInternal("-- FatFileSystem.GetRootDirectory --");
- var xRootEntry = new FatDirectoryEntry(this, null, mRootPath, mSize, mRootPath, RootCluster);
+ var xRootEntry = new FatDiretoryEntry(this, null, mRootPath, mSize, mRootPath, RootCluster);
return xRootEntry;
}
@@ -623,7 +641,7 @@ namespace Cosmos.System.FileSystem.FAT
throw new ArgumentNullException(nameof(aNewDirectory));
}
- var xParentDirectory = (FatDirectoryEntry)aParentDirectory;
+ var xParentDirectory = (FatDiretoryEntry)aParentDirectory;
var xDirectoryEntryToAdd = xParentDirectory.AddDirectoryEntry(aNewDirectory, DirectoryEntryTypeEnum.Directory);
return xDirectoryEntryToAdd;
}
@@ -646,7 +664,8 @@ namespace Cosmos.System.FileSystem.FAT
throw new ArgumentNullException(nameof(aNewFile));
}
- var xParentDirectory = (FatDirectoryEntry)aParentDirectory;
+ var xParentDirectory = (FatDiretoryEntry)aParentDirectory;
+
var xDirectoryEntryToAdd = xParentDirectory.AddDirectoryEntry(aNewFile, DirectoryEntryTypeEnum.File);
return xDirectoryEntryToAdd;
}
@@ -658,7 +677,7 @@ namespace Cosmos.System.FileSystem.FAT
throw new ArgumentNullException(nameof(aDirectoryEntry));
}
- var xDirectoryEntry = (FatDirectoryEntry)aDirectoryEntry;
+ var xDirectoryEntry = (FatDiretoryEntry)aDirectoryEntry;
xDirectoryEntry.DeleteDirectoryEntry();
}
@@ -670,7 +689,7 @@ namespace Cosmos.System.FileSystem.FAT
throw new ArgumentNullException(nameof(aDirectoryEntry));
}
- var xDirectoryEntry = (FatDirectoryEntry)aDirectoryEntry;
+ var xDirectoryEntry = (FatDiretoryEntry)aDirectoryEntry;
var entries = xDirectoryEntry.GetFatTable();
@@ -682,6 +701,64 @@ namespace Cosmos.System.FileSystem.FAT
xDirectoryEntry.DeleteDirectoryEntry();
}
+ public override string mLabel
+ {
+ /*
+ * In the FAT filesystem the name field of RootDirectory is - in reality - the Volume Label
+ */
+ get
+ {
+ Global.mFileSystemDebugger.SendInternal("-- FatFileSystem.mLabel --");
+ var RootDirectory = (FatDiretoryEntry) GetRootDirectory();
+
+ var VolumeId = RootDirectory.FindVolumeId();
+ if (VolumeId == null)
+ {
+ Global.mFileSystemDebugger.SendInternal("No VolumeID, returning drive name");
+ return RootDirectory.mName;
+ }
+
+ Global.mFileSystemDebugger.SendInternal($"Volume label is {VolumeId.mName}");
+ return VolumeId.mName;
+ }
+ set
+ {
+ Global.mFileSystemDebugger.SendInternal($"Setting Volume label to {value}");
+
+ var RootDirectory = (FatDiretoryEntry) GetRootDirectory();
+
+ var VolumeId = RootDirectory.FindVolumeId();
+ if (VolumeId != null)
+ {
+ VolumeId.SetName(value);
+ return;
+ }
+
+ Global.mFileSystemDebugger.SendInternal("No VolumeID found, let's create it!");
+
+ VolumeId = RootDirectory.CreateVolumeId(value);
+ }
+ }
+
+ public override long mAvailableFreeSpace
+ {
+ get
+ {
+ var RootDirectory = (FatDiretoryEntry)GetRootDirectory();
+ // We do not support "user quotas" for now so this is effectively the same then mTotalFreeSpace
+ return mSize - RootDirectory.GetUsedSpace();
+ }
+ }
+
+ public override long mTotalFreeSpace
+ {
+ get
+ {
+ var RootDirectory = (FatDiretoryEntry)GetRootDirectory();
+ return mSize - RootDirectory.GetUsedSpace();
+ }
+ }
+
private enum FatTypeEnum
{
Unknown,
diff --git a/source/Cosmos.System2/FileSystem/FAT/FatStream.cs b/source/Cosmos.System2/FileSystem/FAT/FatStream.cs
index 3579348eb..acef2b9b3 100644
--- a/source/Cosmos.System2/FileSystem/FAT/FatStream.cs
+++ b/source/Cosmos.System2/FileSystem/FAT/FatStream.cs
@@ -15,7 +15,7 @@ namespace Cosmos.System.FileSystem.FAT
protected long mPosition;
- private readonly FatDirectoryEntry mDirectoryEntry;
+ private readonly FatDiretoryEntry mDirectoryEntry;
private readonly FatFileSystem mFS;
@@ -29,7 +29,7 @@ namespace Cosmos.System.FileSystem.FAT
private long mSize;
- public FatStream(FatDirectoryEntry aEntry)
+ public FatStream(FatDiretoryEntry aEntry)
{
if (aEntry == null)
{
diff --git a/source/Cosmos.System2/FileSystem/FAT/Listing/FatDiretoryEntry.cs b/source/Cosmos.System2/FileSystem/FAT/Listing/FatDiretoryEntry.cs
index 0df5601e6..5887811b6 100644
--- a/source/Cosmos.System2/FileSystem/FAT/Listing/FatDiretoryEntry.cs
+++ b/source/Cosmos.System2/FileSystem/FAT/Listing/FatDiretoryEntry.cs
@@ -10,7 +10,7 @@ using Cosmos.System.FileSystem.Listing;
namespace Cosmos.System.FileSystem.FAT.Listing
{
- internal class FatDirectoryEntry : DirectoryEntry
+ internal class FatDiretoryEntry : DirectoryEntry
{
private readonly uint mEntryHeaderDataOffset;
@@ -18,9 +18,9 @@ namespace Cosmos.System.FileSystem.FAT.Listing
// Size is UInt32 because FAT doesn't support bigger.
// Don't change to UInt64
- public FatDirectoryEntry(
+ public FatDiretoryEntry(
FatFileSystem aFileSystem,
- FatDirectoryEntry aParent,
+ FatDiretoryEntry aParent,
string aFullPath,
string aName,
long aSize,
@@ -31,6 +31,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
{
if (aFirstCluster < aFileSystem.RootCluster)
{
+ Global.mFileSystemDebugger.SendInternal($"aFirstCluster {aFirstCluster} < aFileSystem.RootCluster {aFileSystem.RootCluster}");
throw new ArgumentOutOfRangeException(nameof(aFirstCluster));
}
@@ -38,9 +39,9 @@ namespace Cosmos.System.FileSystem.FAT.Listing
mEntryHeaderDataOffset = aEntryHeaderDataOffset;
}
- public FatDirectoryEntry(
+ public FatDiretoryEntry(
FatFileSystem aFileSystem,
- FatDirectoryEntry aParent,
+ FatDiretoryEntry aParent,
string aFullPath,
long aSize,
string aName,
@@ -143,7 +144,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
GetFatTable();
}
- public FatDirectoryEntry AddDirectoryEntry(string aName, DirectoryEntryTypeEnum aEntryType)
+ public FatDiretoryEntry AddDirectoryEntry(string aName, DirectoryEntryTypeEnum aEntryType)
{
Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.AddDirectoryEntry --");
Global.mFileSystemDebugger.SendInternal("aName =");
@@ -203,7 +204,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
}
int n = 1;
- List xDirectoryEntries = ReadDirectoryContents(true);
+ List xDirectoryEntries = ReadDirectoryContents(true);
string[] xShortFilenames = new string[xDirectoryEntries.Count];
for (int i = 0; i < xDirectoryEntries.Count; i++)
@@ -279,7 +280,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
Global.mFileSystemDebugger.SendInternal("xEntryHeaderDataOffset =");
Global.mFileSystemDebugger.SendInternal(xEntryHeaderDataOffset);
- var xNewEntry = new FatDirectoryEntry((FatFileSystem)mFileSystem, this, xFullPath, aName, 0, xFirstCluster, xEntryHeaderDataOffset, aEntryType);
+ var xNewEntry = new FatDiretoryEntry((FatFileSystem)mFileSystem, this, xFullPath, aName, 0, xFirstCluster, xEntryHeaderDataOffset, aEntryType);
xNewEntry.AllocateDirectoryEntry(xShortName);
@@ -289,6 +290,8 @@ namespace Cosmos.System.FileSystem.FAT.Listing
throw new ArgumentOutOfRangeException(nameof(aEntryType), "Unknown directory entry type.");
}
+ private bool IsRootDirectory() => (mParent == null) ? true : false;
+
public void DeleteDirectoryEntry()
{
if (mEntryType == DirectoryEntryTypeEnum.Unknown)
@@ -296,25 +299,23 @@ namespace Cosmos.System.FileSystem.FAT.Listing
throw new NotImplementedException();
}
- if (mParent != null)
+ if (IsRootDirectory())
{
- var xData = ((FatDirectoryEntry)mParent).GetDirectoryEntryData();
-
- var xEntryOffset = mEntryHeaderDataOffset - 32;
-
- while (xData[xEntryOffset + 11] == FatDirectoryEntryAttributeConsts.LongName)
- {
- xData[xEntryOffset] = FatDirectoryEntryAttributeConsts.UnusedOrDeletedEntry;
- xEntryOffset -= 32;
- }
-
- ((FatDirectoryEntry)mParent).SetDirectoryEntryData(xData);
+ throw new Exception("Root directory can not be deleted");
}
- else
+
+ var xData = ((FatDiretoryEntry)mParent).GetDirectoryEntryData();
+
+ var xEntryOffset = mEntryHeaderDataOffset - 32;
+
+ while (xData[xEntryOffset + 11] == FatDirectoryEntryAttributeConsts.LongName)
{
- throw new Exception("Parent directory is null");
+ xData[xEntryOffset] = FatDirectoryEntryAttributeConsts.UnusedOrDeletedEntry;
+ xEntryOffset -= 32;
}
+ ((FatDiretoryEntry)mParent).SetDirectoryEntryData(xData);
+
SetDirectoryEntryMetadataValue(FatDirectoryEntryMetadata.FirstByte, FatDirectoryEntryAttributeConsts.UnusedOrDeletedEntry);
// GetFatTable calls GetFatChain, which "refreshes" the FAT table and clusters
@@ -322,16 +323,16 @@ namespace Cosmos.System.FileSystem.FAT.Listing
}
///
- /// Retrieves a of objects that represent the Directory Entries inside this Directory
+ /// Retrieves a of objects that represent the Directory Entries inside this Directory
///
/// Returns a of the Directory Entries inside this Directory
- public List ReadDirectoryContents(bool aReturnShortFilenames = false)
+ public List ReadDirectoryContents(bool aReturnShortFilenames = false)
{
Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.ReadDirectoryContents --");
var xData = GetDirectoryEntryData();
- var xResult = new List();
- FatDirectoryEntry xParent = this;
+ var xResult = new List();
+ FatDiretoryEntry xParent = this;
//TODO: Change xLongName to StringBuilder
string xLongName = "";
@@ -474,7 +475,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
}
string xFullPath = Path.Combine(mFullPath, xName);
- var xEntry = new FatDirectoryEntry(((FatFileSystem)mFileSystem), xParent, xFullPath, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.File);
+ var xEntry = new FatDiretoryEntry(((FatFileSystem)mFileSystem), xParent, xFullPath, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.File);
xResult.Add(xEntry);
Global.mFileSystemDebugger.SendInternal(xEntry.mName + " - " + xEntry.mSize + " bytes");
}
@@ -482,7 +483,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
{
string xFullPath = Path.Combine(mFullPath, xName);
uint xSize = xData.ToUInt32(i + 28);
- var xEntry = new FatDirectoryEntry(((FatFileSystem)mFileSystem), xParent, xFullPath, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.Directory);
+ var xEntry = new FatDiretoryEntry(((FatFileSystem)mFileSystem), xParent, xFullPath, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.Directory);
Global.mFileSystemDebugger.SendInternal(xEntry.mName + " " + xEntry.mSize + " bytes : Attrib = " + xAttrib + ", Status = " + xStatus);
xResult.Add(xEntry);
}
@@ -502,6 +503,62 @@ namespace Cosmos.System.FileSystem.FAT.Listing
return xResult;
}
+ public FatDiretoryEntry FindVolumeId()
+ {
+ if (!IsRootDirectory())
+ {
+ throw new Exception("VolumeId can be found only in Root Directory");
+ }
+
+ Global.mFileSystemDebugger.SendInternal("-- FatDirectoryEntry.FindVolumeId --");
+
+ var xData = GetDirectoryEntryData();
+ FatDiretoryEntry xParent = this;
+
+ FatDiretoryEntry xResult = null;
+ for (uint i = 0; i < xData.Length; i = i + 32)
+ {
+ byte xAttrib = xData[i + 11];
+
+ //if ((xAttrib & FatDirectoryEntryAttributeConsts.VolumeID) != FatDirectoryEntryAttributeConsts.VolumeID)
+ if (xAttrib != FatDirectoryEntryAttributeConsts.VolumeID)
+ continue;
+
+ Global.mFileSystemDebugger.SendInternal("VolumeID Found");
+ /* The Label in FAT could be only a shortName (limited to 11 characters) so it is more easy */
+ string xName = xData.GetAsciiString(i, 11).TrimEnd();
+ string xFullPath = Path.Combine(mFullPath, xName);
+ /* Probably can be OK to hardcode 0 here */
+ uint xSize = xData.ToUInt32(i + 28);
+ //uint xFirstCluster = (uint)(xData.ToUInt16(i + 20) << 16 | xData.ToUInt16(i + 26));
+ uint xFirstCluster = xParent.mFirstClusterNum;
+
+ Global.mFileSystemDebugger.SendInternal($"VolumeID Found xName {xName} xFullPath {xFullPath} xSize {xSize} xFirstCluster {xFirstCluster}");
+
+ xResult = new FatDiretoryEntry(((FatFileSystem)mFileSystem), xParent, xFullPath, xName, xSize, xFirstCluster, i, DirectoryEntryTypeEnum.File);
+ break;
+ }
+
+ if (xResult == null)
+ Global.mFileSystemDebugger.SendInternal($"VolumeID not found, returning null");
+
+ return xResult;
+ }
+
+ public FatDiretoryEntry CreateVolumeId(string name)
+ {
+ if (!IsRootDirectory())
+ {
+ throw new Exception("VolumeId can be created only in Root Directory");
+ }
+
+ // VolumeId is really a special type of File with attribute 'VolumeID' set
+ var VolumeId = AddDirectoryEntry(name, DirectoryEntryTypeEnum.File);
+ VolumeId.SetDirectoryEntryMetadataValue(FatDirectoryEntryMetadata.Attributes, FatDirectoryEntryAttributeConsts.VolumeID);
+
+ return VolumeId;
+ }
+
///
/// Tries to find an empty space for a directory entry and returns the offset to that space if successful, otherwise throws an exception.
///
@@ -614,23 +671,21 @@ namespace Cosmos.System.FileSystem.FAT.Listing
Global.mFileSystemDebugger.SendInternal("aValue =");
Global.mFileSystemDebugger.SendInternal(aValue);
- if (mParent != null)
- {
- var xData = ((FatDirectoryEntry)mParent).GetDirectoryEntryData();
-
- if (xData.Length > 0)
- {
- var xValue = new byte[aEntryMetadata.DataLength];
- xValue.SetUInt32(0, aValue);
- uint offset = mEntryHeaderDataOffset + aEntryMetadata.DataOffset;
- Array.Copy(xValue, 0, xData, offset, aEntryMetadata.DataLength);
- ((FatDirectoryEntry)mParent).SetDirectoryEntryData(xData);
- }
- }
- else
+ if (IsRootDirectory())
{
throw new Exception("Root directory metadata can not be changed using the file stream.");
}
+
+ var xData = ((FatDiretoryEntry)mParent).GetDirectoryEntryData();
+
+ if (xData.Length > 0)
+ {
+ var xValue = new byte[aEntryMetadata.DataLength];
+ xValue.SetUInt32(0, aValue);
+ uint offset = mEntryHeaderDataOffset + aEntryMetadata.DataOffset;
+ Array.Copy(xValue, 0, xData, offset, aEntryMetadata.DataLength);
+ ((FatDiretoryEntry)mParent).SetDirectoryEntryData(xData);
+ }
}
internal void SetDirectoryEntryMetadataValue(FatDirectoryEntryMetadata aEntryMetadata, long aValue)
@@ -639,25 +694,23 @@ namespace Cosmos.System.FileSystem.FAT.Listing
Global.mFileSystemDebugger.SendInternal("aValue =");
Global.mFileSystemDebugger.SendInternal(aValue);
- if (mParent != null)
- {
- var xData = ((FatDirectoryEntry)mParent).GetDirectoryEntryData();
-
- if (xData.Length > 0)
- {
- var xValue = new byte[aEntryMetadata.DataLength];
- xValue.SetUInt32(0, (uint)aValue);
- uint offset = mEntryHeaderDataOffset + aEntryMetadata.DataOffset;
- Global.mFileSystemDebugger.SendInternal("offset =");
- Global.mFileSystemDebugger.SendInternal(offset);
- Array.Copy(xValue, 0, xData, offset, aEntryMetadata.DataLength);
- ((FatDirectoryEntry)mParent).SetDirectoryEntryData(xData);
- }
- }
- else
+ if (IsRootDirectory())
{
throw new Exception("Root directory metadata can not be changed using the file stream.");
}
+
+ var xData = ((FatDiretoryEntry)mParent).GetDirectoryEntryData();
+
+ if (xData.Length > 0)
+ {
+ var xValue = new byte[aEntryMetadata.DataLength];
+ xValue.SetUInt32(0, (uint)aValue);
+ uint offset = mEntryHeaderDataOffset + aEntryMetadata.DataOffset;
+ Global.mFileSystemDebugger.SendInternal("offset =");
+ Global.mFileSystemDebugger.SendInternal(offset);
+ Array.Copy(xValue, 0, xData, offset, aEntryMetadata.DataLength);
+ ((FatDiretoryEntry)mParent).SetDirectoryEntryData(xData);
+ }
}
internal void SetDirectoryEntryMetadataValue(FatDirectoryEntryMetadata aEntryMetadata, string aValue)
@@ -666,7 +719,12 @@ namespace Cosmos.System.FileSystem.FAT.Listing
Global.mFileSystemDebugger.SendInternal("aValue =");
Global.mFileSystemDebugger.SendInternal(aValue);
- var xData = ((FatDirectoryEntry)mParent).GetDirectoryEntryData();
+ if (IsRootDirectory())
+ {
+ throw new Exception("Root directory metadata can not be changed using the file stream.");
+ }
+
+ var xData = ((FatDiretoryEntry)mParent).GetDirectoryEntryData();
if (xData.Length > 0)
{
@@ -676,7 +734,7 @@ namespace Cosmos.System.FileSystem.FAT.Listing
uint offset = mEntryHeaderDataOffset + aEntryMetadata.DataOffset;
Array.Copy(xValue, 0, xData, offset, aEntryMetadata.DataLength);
- ((FatDirectoryEntry)mParent).SetDirectoryEntryData(xData);
+ ((FatDiretoryEntry)mParent).SetDirectoryEntryData(xData);
}
}
@@ -791,5 +849,100 @@ namespace Cosmos.System.FileSystem.FAT.Listing
return xChecksum;
}
+
+ private long GetDirectoryEntrySize(byte[] DirectoryEntryData)
+ {
+ long xResult = 0;
+
+ for (uint i = 0; i < DirectoryEntryData.Length; i = i + 32)
+ {
+ byte xAttrib = DirectoryEntryData[i + 11];
+ byte xStatus = DirectoryEntryData[i];
+
+ if (xAttrib == FatDirectoryEntryAttributeConsts.LongName)
+ {
+ //Global.mFileSystemDebugger.SendInternal($"-- FatDirectoryEntry.GetDirectoryEntrySize() LongName DirEntry skipped!");
+ continue;
+ }
+
+ if (xStatus == 0x00)
+ {
+ //Global.mFileSystemDebugger.SendInternal(" : Attrib = " + xAttrib + ", Status = " + xStatus);
+ break;
+ }
+
+ switch (xStatus)
+ {
+ case 0x05:
+ // Japanese characters - We dont handle these
+ continue;
+ case 0x2E:
+ // Dot entry
+ continue;
+ case FatDirectoryEntryAttributeConsts.UnusedOrDeletedEntry:
+ // Empty slot, skip it
+ continue;
+
+ default:
+ break;
+ }
+
+ int xTest = xAttrib & (FatDirectoryEntryAttributeConsts.Directory | FatDirectoryEntryAttributeConsts.VolumeID);
+
+ switch (xTest)
+ {
+ // Normal file
+ case 0:
+ uint xSize = DirectoryEntryData.ToUInt32(i + 28);
+ xResult += xSize;
+ break;
+
+ case FatDirectoryEntryAttributeConsts.Directory:
+ //Global.mFileSystemDebugger.SendInternal($"-- FatDirectoryEntry.GetDirectoryEntrySize() found directory: recursing!");
+
+ uint xFirstCluster = (uint)(DirectoryEntryData.ToUInt16(i + 20) << 16 | DirectoryEntryData.ToUInt16(i + 26));
+ byte[] xDirData;
+ ((FatFileSystem)mFileSystem).Read(xFirstCluster, out xDirData);
+
+ xResult += GetDirectoryEntrySize(xDirData);
+ break;
+
+ case FatDirectoryEntryAttributeConsts.VolumeID:
+ //Global.mFileSystemDebugger.SendInternal(": skipped");
+ continue;
+
+ default:
+ //Global.mFileSystemDebugger.SendInternal(": skipped");
+ continue;
+ }
+ }
+
+ //Global.mFileSystemDebugger.SendInternal($"-- FatDirectoryEntry.GetDirectoryEntrySize() is {xResult} bytes");
+ return xResult;
+ }
+
+ /*
+ * Please note that this could become slower and slower as the partion becomes greater this could be optimized in two ways:
+ * 1. Compute the value using this function on FS inizialization and write the difference between TotalSpace and the computed
+ * value to the specif field of 'FS Information Sector' of FAT32
+ * 2. Compute the value using this function on FS inizialization and write the difference between TotalSpace and the computed
+ * value in a sort of memory cache in VFS itself
+ *
+ * In any case if one of this two methods will be used in the future when a file is removed or new data are written on it,
+ * the value on the field should be always updated.
+ */
+ public override long GetUsedSpace()
+ {
+ Global.mFileSystemDebugger.SendInternal($"-- FatDirectoryEntry.GetUsedSpace() on Directory {mName} ---");
+
+ long xResult = 0;
+
+ var xData = GetDirectoryEntryData();
+
+ xResult += GetDirectoryEntrySize(xData);
+
+ Global.mFileSystemDebugger.SendInternal($"-- FatDirectoryEntry.GetUsedSpace() is {xResult} bytes");
+ return xResult;
+ }
}
}
diff --git a/source/Cosmos.System2/FileSystem/FatFileSystemFactory.cs b/source/Cosmos.System2/FileSystem/FatFileSystemFactory.cs
new file mode 100644
index 000000000..68c84fd2d
--- /dev/null
+++ b/source/Cosmos.System2/FileSystem/FatFileSystemFactory.cs
@@ -0,0 +1,23 @@
+using Cosmos.HAL.BlockDevice;
+using Cosmos.System.FileSystem.FAT;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Cosmos.System.FileSystem
+{
+ public class FatFileSystemFactory : FileSystemFactory
+ {
+ public override string Name { get => "FAT"; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The partition.
+ /// The root path.
+ /// FAT signature not found.
+ public override FileSystem Create(Partition aDevice, string aRootPath, long aSize) => new FatFileSystem(aDevice, aRootPath, aSize);
+
+ public override bool IsType(Partition aDevice) => FatFileSystem.IsDeviceFat(aDevice);
+ }
+}
diff --git a/source/Cosmos.System2/FileSystem/FileSystem.cs b/source/Cosmos.System2/FileSystem/FileSystem.cs
index 5486127f2..6e8f2a2ab 100644
--- a/source/Cosmos.System2/FileSystem/FileSystem.cs
+++ b/source/Cosmos.System2/FileSystem/FileSystem.cs
@@ -16,16 +16,6 @@ namespace Cosmos.System.FileSystem
mSize = aSize;
}
- public static FileSystemType GetFileSystemType(Partition aDevice)
- {
- if (FatFileSystem.IsDeviceFat(aDevice))
- {
- return FileSystemType.FAT;
- }
-
- return FileSystemType.Unknown;
- }
-
public abstract void DisplayFileSystemInfo();
public abstract List GetDirectoryListing(DirectoryEntry baseDirectory);
@@ -45,5 +35,13 @@ namespace Cosmos.System.FileSystem
public string mRootPath { get; }
public long mSize { get; }
+
+ public abstract long mAvailableFreeSpace { get; }
+
+ public abstract long mTotalFreeSpace { get; }
+
+ public abstract string mType { get; }
+
+ public abstract string mLabel { get; set; }
}
}
diff --git a/source/Cosmos.System2/FileSystem/FileSystemFactory.cs b/source/Cosmos.System2/FileSystem/FileSystemFactory.cs
new file mode 100644
index 000000000..ce2471798
--- /dev/null
+++ b/source/Cosmos.System2/FileSystem/FileSystemFactory.cs
@@ -0,0 +1,16 @@
+using Cosmos.HAL.BlockDevice;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Cosmos.System.FileSystem
+{
+ public class FileSystemFactory
+ {
+ public virtual string Name { get; private set; }
+
+ public virtual FileSystem Create(Partition aDevice, string aRootPath, long aSize) => null;
+
+ public virtual bool IsType(Partition aDevice) => false;
+ }
+}
diff --git a/source/Cosmos.System2/FileSystem/FileSystemType.cs b/source/Cosmos.System2/FileSystem/FileSystemType.cs
index 1197e3253..d11e5e06f 100644
--- a/source/Cosmos.System2/FileSystem/FileSystemType.cs
+++ b/source/Cosmos.System2/FileSystem/FileSystemType.cs
@@ -2,7 +2,7 @@
{
public enum FileSystemType
{
+ Unknown = 0,
FAT,
- Unknown
}
-}
\ No newline at end of file
+}
diff --git a/source/Cosmos.System2/FileSystem/Listing/DirectoryEntry.cs b/source/Cosmos.System2/FileSystem/Listing/DirectoryEntry.cs
index 4ac7ef2cb..95749a93b 100644
--- a/source/Cosmos.System2/FileSystem/Listing/DirectoryEntry.cs
+++ b/source/Cosmos.System2/FileSystem/Listing/DirectoryEntry.cs
@@ -79,5 +79,7 @@ namespace Cosmos.System.FileSystem.Listing
public abstract void SetSize(long aSize);
public abstract Stream GetFileStream();
+
+ public abstract long GetUsedSpace();
}
-}
\ No newline at end of file
+}
diff --git a/source/Cosmos.System2/FileSystem/VFS/VFSBase.cs b/source/Cosmos.System2/FileSystem/VFS/VFSBase.cs
index 1c5770379..57b8ec731 100644
--- a/source/Cosmos.System2/FileSystem/VFS/VFSBase.cs
+++ b/source/Cosmos.System2/FileSystem/VFS/VFSBase.cs
@@ -8,6 +8,8 @@ namespace Cosmos.System.FileSystem.VFS
{
public abstract void Initialize();
+ public abstract void RegisterFileSystem(FileSystemFactory aFileSystemFactory);
+
public abstract DirectoryEntry CreateFile(string aPath);
public abstract DirectoryEntry CreateDirectory(string aPath);
@@ -37,5 +39,19 @@ namespace Cosmos.System.FileSystem.VFS
public static char AltDirectorySeparatorChar { get { return '/'; } }
public static char VolumeSeparatorChar { get { return ':'; } }
+
+ public abstract bool IsValidDriveId(string driveId);
+
+ public abstract long GetTotalSize(string aDriveId);
+
+ public abstract long GetAvailableFreeSpace(string aDriveId);
+
+ public abstract long GetTotalFreeSpace(string aDriveId);
+
+ public abstract string GetFileSystemType(string aDriveId);
+
+ public abstract string GetFileSystemLabel(string aDriveId);
+
+ public abstract void SetFileSystemLabel(string aDriveId, string aLabel);
}
}
diff --git a/source/Cosmos.System2/FileSystem/VFS/VFSManager.cs b/source/Cosmos.System2/FileSystem/VFS/VFSManager.cs
index b4418ff5d..de21c6c03 100644
--- a/source/Cosmos.System2/FileSystem/VFS/VFSManager.cs
+++ b/source/Cosmos.System2/FileSystem/VFS/VFSManager.cs
@@ -201,19 +201,20 @@ namespace Cosmos.System.FileSystem.VFS
return mVFS.GetVolumes();
}
+ public static void RegisterFileSystem(FileSystemFactory aFileSystemFactory)
+ {
+ mVFS.RegisterFileSystem(aFileSystemFactory);
+ }
+
public static List GetLogicalDrives()
{
Global.mFileSystemDebugger.SendInternal("--- VFSManager.GetLogicalDrives ---");
- //TODO: Directory.GetLogicalDrives() will call this.
- return null;
-
- /*
List xDrives = new List();
- foreach (FilesystemEntry entry in GetVolumes())
- xDrives.Add(entry.Name + Path.VolumeSeparatorChar + Path.DirectorySeparatorChar);
- return xDrives.ToArray();
- */
+ foreach (DirectoryEntry entry in GetVolumes())
+ xDrives.Add(entry.mName + Path.VolumeSeparatorChar + Path.DirectorySeparatorChar);
+
+ return xDrives;
}
public static List InternalGetFileDirectoryNames(
@@ -430,6 +431,43 @@ namespace Cosmos.System.FileSystem.VFS
Global.mFileSystemDebugger.SendInternal("--- VFSManager.GetFileAttributes ---");
mVFS.SetFileAttributes(aPath, fileAttributes);
}
+
+ public static bool IsValidDriveId(string aPath)
+ {
+ Global.mFileSystemDebugger.SendInternal("--- VFSManager.GetFileAttributes ---");
+ return mVFS.IsValidDriveId(aPath);
+ }
+
+ public static long GetTotalSize(string aDriveId)
+ {
+ return mVFS.GetTotalSize(aDriveId);
+ }
+
+ public static long GetAvailableFreeSpace(string aDriveId)
+ {
+ return mVFS.GetAvailableFreeSpace(aDriveId);
+ }
+
+ public static long GetTotalFreeSpace(string aDriveId)
+ {
+ return mVFS.GetTotalFreeSpace(aDriveId);
+ }
+
+ public static string GetFileSystemType(string aDriveId)
+ {
+ return mVFS.GetFileSystemType(aDriveId);
+ }
+
+ public static string GetFileSystemLabel(string aDriveId)
+ {
+ return mVFS.GetFileSystemLabel(aDriveId);
+ }
+
+ public static void SetFileSystemLabel(string aDriveId, string aLabel)
+ {
+ mVFS.SetFileSystemLabel(aDriveId, aLabel);
+ }
+
#region Helpers
public static char GetAltDirectorySeparatorChar()
diff --git a/source/Cosmos.System2_Plugs/System/IO/CosmosDriveInfo.cs b/source/Cosmos.System2_Plugs/System/IO/CosmosDriveInfo.cs
new file mode 100644
index 000000000..bd05171ed
--- /dev/null
+++ b/source/Cosmos.System2_Plugs/System/IO/CosmosDriveInfo.cs
@@ -0,0 +1,115 @@
+//#define COSMOSDEBUG
+using Cosmos.System;
+using Cosmos.System.FileSystem;
+using Cosmos.System.FileSystem.VFS;
+using IL2CPU.API.Attribs;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Cosmos.System_Plugs.System.IO
+{
+ [Plug(Target = typeof(DriveInfo))]
+ public static class DriveInfoImpl
+ {
+ public static string NormalizeDriveName(string driveName)
+ {
+ string name;
+
+ if (driveName.Length == 1)
+ name = driveName + ":\\";
+ else
+ {
+ name = Path.GetPathRoot(driveName);
+ // Disallow null or empty drive letters and UNC paths
+ if (name == null || name.Length == 0 || name.StartsWith("\\\\", StringComparison.Ordinal))
+ throw new ArgumentException("Argument must be drive identifier or root dir");
+ }
+ // We want to normalize to have a trailing backslash so we don't have two equivalent forms and
+ // because some Win32 API don't work without it.
+ if (name.Length == 2 && name[1] == ':')
+ {
+ name = name + "\\";
+ }
+
+ if (!VFSManager.IsValidDriveId(name))
+ {
+ throw new ArgumentException("Argument must be drive identifier or root dir");
+ }
+
+ return name;
+ }
+
+ public static long get_AvailableFreeSpace(DriveInfo aThis)
+ {
+ Global.mFileSystemDebugger.SendInternal($"Getting Available Free Space of {aThis.Name}");
+
+ return VFSManager.GetAvailableFreeSpace(aThis.Name);
+ }
+
+ public static long get_TotalFreeSpace(DriveInfo aThis)
+ {
+ Global.mFileSystemDebugger.SendInternal($"Getting Total Free Space of {aThis.Name}");
+
+ return VFSManager.GetTotalFreeSpace(aThis.Name);
+ }
+
+ public static long get_TotalSize(DriveInfo aThis)
+ {
+ Global.mFileSystemDebugger.SendInternal($"Getting size of {aThis.Name}");
+
+ return VFSManager.GetTotalSize(aThis.Name);
+ }
+
+ public static string get_DriveFormat(DriveInfo aThis)
+ {
+ Global.mFileSystemDebugger.SendInternal($"Getting format of {aThis.Name}");
+
+ return VFSManager.GetFileSystemType(aThis.Name);
+ }
+
+ public static string get_VolumeLabel(DriveInfo aThis)
+ {
+ Global.mFileSystemDebugger.SendInternal($"Getting label of {aThis.Name}");
+
+ return VFSManager.GetFileSystemLabel(aThis.Name);
+ }
+
+ public static void set_VolumeLabel(DriveInfo aThis, string aLabel)
+ {
+ Global.mFileSystemDebugger.SendInternal($"Setting label of {aThis.Name} with {aLabel}");
+
+ VFSManager.SetFileSystemLabel(aThis.Name, aLabel);
+ }
+
+ /* For now I'm forcing IsReady to be always true as only fixed drives are supported in Cosmos for now */
+ public static bool get_IsReady(DriveInfo aThis)
+ {
+ Global.mFileSystemDebugger.SendInternal($"Getting isReady status of {aThis.Name}");
+ return true;
+ }
+
+ /* For now I'm forcing DriveType to always be 'Fixed' as only fixed drives are supported in Cosmos for now */
+ public static DriveType get_DriveType(DriveInfo aThis)
+ {
+ Global.mFileSystemDebugger.SendInternal($"Getting DriveType of {aThis.Name}");
+ return DriveType.Fixed;
+ }
+
+ public static DriveInfo[] GetDrives()
+ {
+ Global.mFileSystemDebugger.SendInternal("GetDrives called");
+
+ List drives = VFSManager.GetLogicalDrives();
+
+ DriveInfo[] result = new DriveInfo[drives.Count];
+ for (int i = 0; i < drives.Count; i++)
+ {
+ result[i] = new DriveInfo(drives[i]);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/source/Cosmos.System2_Plugs/System/Int32Impl.cs b/source/Cosmos.System2_Plugs/System/Int32Impl.cs
index 76d855515..ce9acf32c 100644
--- a/source/Cosmos.System2_Plugs/System/Int32Impl.cs
+++ b/source/Cosmos.System2_Plugs/System/Int32Impl.cs
@@ -46,5 +46,20 @@ namespace Cosmos.System_Plugs.System
return result;
}
+
+ /* .Net Core TryParse is calling Number.TryParse() that does NRE in Cosmos, plugged it for now */
+ public static bool TryParse(string s, out int result)
+ {
+ try
+ {
+ result = Int32.Parse(s);
+ return true;
+ }
+ catch
+ {
+ result = 0;
+ return false;
+ }
+ }
}
}