//#define COSMOSDEBUG using System; using System.IO; using Cosmos.Common; using Cosmos.Debug.Kernel; using Cosmos.IL2CPU.Plugs; using Cosmos.System.FileSystem; using Cosmos.System.FileSystem.VFS; namespace Cosmos.System.Plugs.System.IO { [Plug(Target = typeof(Path))] public static class PathImpl { public static void Cctor( [FieldAccess(Name = "System.Char System.IO.Path.AltDirectorySeparatorChar")] ref char aAltDirectorySeparatorChar, [FieldAccess(Name = "System.Char System.IO.Path.DirectorySeparatorChar")] ref char aDirectorySeparatorChar, [FieldAccess(Name = "System.Char System.IO.Path.VolumeSeparatorChar")] ref char aVolumeSeparatorChar) { aAltDirectorySeparatorChar = VFSManager.GetAltDirectorySeparatorChar(); aDirectorySeparatorChar = VFSManager.GetDirectorySeparatorChar(); aVolumeSeparatorChar = VFSManager.GetVolumeSeparatorChar(); } public static string ChangeExtension(string aPath, string aExtension) { if (aPath != null) { CheckInvalidPathChars(aPath); string xText = aPath; int xNum = aPath.Length; while (--xNum >= 0) { char xC = aPath[xNum]; if (xC == '.') { xText = aPath.Substring(0, xNum); break; } if (xC == Path.DirectorySeparatorChar || xC == Path.AltDirectorySeparatorChar || xC == Path.VolumeSeparatorChar) { break; } } if (aExtension != null && aPath.Length != 0) { if (aExtension.Length == 0 || aExtension[0] != '.') { xText += "."; } xText += aExtension; } Global.mFileSystemDebugger.SendInternal($"Path.ChangeExtension : aPath = {aPath}, aExtension = {aExtension}, returning {xText}"); return xText; } return null; } public static string Combine(string aPath1, string aPath2) { if (aPath1 == null || aPath2 == null) { throw new ArgumentNullException((aPath1 == null) ? "path1" : "path2"); } CheckInvalidPathChars(aPath1); CheckInvalidPathChars(aPath2); string result = CombineNoChecks(aPath1, aPath2); Global.mFileSystemDebugger.SendInternal($"Path.Combine : aPath1 = {aPath1}, aPath2 = {aPath2}, returning {result}"); return result; } public static string CombineNoChecks(string aPath1, string aPath2) { if (aPath2.Length == 0) { Global.mFileSystemDebugger.SendInternal($"Path.CombineNoChecks : aPath2 has 0 length, returning {aPath1}"); return aPath1; } if (aPath1.Length == 0) { Global.mFileSystemDebugger.SendInternal($"Path.CombineNoChecks : aPath1 has 0 length, returning {aPath2}"); return aPath2; } if (IsPathRooted(aPath2)) { Global.mFileSystemDebugger.SendInternal($"Path.CombineNoChecks : aPath2 is root, returning {aPath2}"); return aPath2; } string xResult = string.Empty; char xC = aPath1[aPath1.Length - 1]; if (xC != Path.DirectorySeparatorChar && xC != Path.AltDirectorySeparatorChar && xC != Path.VolumeSeparatorChar) { xResult = string.Concat(aPath1, "\\", aPath2); Global.mFileSystemDebugger.SendInternal($"Path.CombineNoChecks : aPath1 = {aPath1}, aPath2 = {aPath2}, returning {xResult}"); return xResult; } xResult = string.Concat(aPath1, aPath2); Global.mFileSystemDebugger.SendInternal($"Path.CombineNoChecks : aPath1 = {aPath1}, aPath2 = {aPath2}, returning {xResult}"); return xResult; } public static string GetExtension(string aPath) { Global.mFileSystemDebugger.SendInternal("Path.GetExtension"); if (aPath == null) { return null; } CheckInvalidPathChars(aPath); int xLength = aPath.Length; int xNum = xLength; while (--xNum >= 0) { char xC = aPath[xNum]; if (xC == '.') { if (xNum != xLength - 1) { return aPath.Substring(xNum, xLength - xNum); } return string.Empty; } if (xC == Path.DirectorySeparatorChar || xC == Path.AltDirectorySeparatorChar || xC == Path.VolumeSeparatorChar) { break; } } return string.Empty; } public static string GetFileName(string aPath) { Global.mFileSystemDebugger.SendInternal($"Path.GetFileName : aPath = {aPath}"); if (aPath != null) { CheckInvalidPathChars(aPath); int xLength = aPath.Length; int xNum = xLength; while (--xNum >= 0) { char xC = aPath[xNum]; if (xC == Path.DirectorySeparatorChar || xC == Path.AltDirectorySeparatorChar || xC == Path.VolumeSeparatorChar) { return aPath.Substring(xNum + 1, xLength - xNum - 1); } } } Global.mFileSystemDebugger.SendInternal($"Path.GetFileName : returning {aPath}"); return aPath; } public static string GetFileNameWithoutExtension(string aPath) { Global.mFileSystemDebugger.SendInternal($"Path.GetFileNameWithoutExtension : aPath = {aPath}"); aPath = GetFileName(aPath); if (aPath == null) { Global.mFileSystemDebugger.SendInternal($"Path.GetFileNameWithoutExtension : returning null"); return null; } int xLength; if ((xLength = aPath.LastIndexOf('.')) == -1) { Global.mFileSystemDebugger.SendInternal($"Path.GetFileNameWithoutExtension : returning {aPath}"); return aPath; } string xResult = aPath.Substring(0, xLength); Global.mFileSystemDebugger.SendInternal($"Path.GetFileNameWithoutExtension : returning {xResult}"); return xResult; } public static string GetFullPath(string aPath) { if (aPath == null) { Global.mFileSystemDebugger.SendInternal($"Path.GetFullPath : aPath is null"); throw new ArgumentNullException("aPath"); } string result = NormalizePath(aPath, true); Global.mFileSystemDebugger.SendInternal($"Path.GetFullPath : aPath = {aPath}, returning {result}"); return result; } public static char[] GetInvalidFileNameChars() { return VFSManager.GetInvalidFileNameChars(); } public static char[] GetInvalidPathChars() { return VFSManager.GetRealInvalidPathChars(); } public static string GetPathRoot(string aPath) { if (aPath == null) { Global.mFileSystemDebugger.SendInternal($"Path.GetPathRoot : aPath is null"); throw new ArgumentNullException(nameof(aPath)); } aPath = NormalizePath(aPath, false); int xRootLength = GetRootLength(aPath); string xResult = aPath.Substring(0, xRootLength); if (xResult[xResult.Length - 1] != Path.DirectorySeparatorChar) { xResult = string.Concat(xResult, Path.DirectorySeparatorChar); } Global.mFileSystemDebugger.SendInternal($"Path.GetPathRoot : aPath = {aPath}, xResult = {xResult}"); return xResult; } public static string GetRandomFileName() { return "random.tmp"; } public static string GetTempFileName() { return "tempfile.tmp"; } public static string GetTempPath() { return @"\Temp"; } public static string RemoveLongPathPrefix(string aPath) { return aPath; } public static bool HasExtension(string aPath) { if (aPath != null) { CheckInvalidPathChars(aPath); int xNum = aPath.Length; while (--xNum >= 0) { char xC = aPath[xNum]; if (xC == '.') { return xNum != aPath.Length - 1; } if (xC == Path.DirectorySeparatorChar || xC == Path.AltDirectorySeparatorChar || xC == Path.VolumeSeparatorChar) { break; } } } return false; } [PlugMethod(IsOptional = true)] public static bool HasIllegalCharacters(string aPath, bool aCheckAdditional) { if (aCheckAdditional) { char[] xInvalidWithAdditional = VFSManager.GetInvalidPathCharsWithAdditionalChecks(); for (int i = 0; i < xInvalidWithAdditional.Length; i++) { for (int j = 0; j < aPath.Length; j++) { if (xInvalidWithAdditional[i] == aPath[j]) { return true; } } } } char[] xInvalid = VFSManager.GetRealInvalidPathChars(); for (int i = 0; i < xInvalid.Length; i++) { for (int j = 0; j < aPath.Length; j++) { if (xInvalid[i] == aPath[j]) { return true; } } } return false; } public static bool IsDirectorySeparator(char aC) { if (aC == Path.DirectorySeparatorChar) { return true; } if (aC == Path.AltDirectorySeparatorChar) { return true; } return false; } public static bool IsPathRooted(string aPath) { Global.mFileSystemDebugger.SendInternal("Path.IsPathRooted"); if (aPath != null) { CheckInvalidPathChars(aPath); int xLength = aPath.Length; if ((xLength >= 1 && (aPath[0] == Path.DirectorySeparatorChar || aPath[0] == Path.AltDirectorySeparatorChar)) || (xLength >= 2 && aPath[1] == Path.VolumeSeparatorChar)) { return true; } } return false; } private static bool IsRelative(string aPath) { if (aPath == null) { throw new ArgumentNullException("aPath"); } if (aPath.Length < 3) { return true; } if (aPath[1] != Path.VolumeSeparatorChar) { return true; } if (aPath[2] != Path.DirectorySeparatorChar) { return true; } return false; } internal static void CheckInvalidPathChars(string aPath, bool aCheckAdditional = false) { Global.mFileSystemDebugger.SendInternal("Path.CheckInvalidPathChars"); if (aPath == null) { throw new ArgumentNullException("aPath"); } Global.mFileSystemDebugger.SendInternal("aPath ="); Global.mFileSystemDebugger.SendInternal(aPath); var xChars = VFSManager.GetRealInvalidPathChars(); for (int i = 0; i < xChars.Length; i++) { if (aPath.IndexOf(xChars[i]) >= 0) { throw new ArgumentException("The path contains invalid characters.", aPath); } } } public static string GetDirectoryName(string aPath) { Global.mFileSystemDebugger.SendInternal("Path.GetDirectoryName"); if (aPath != null) { Global.mFileSystemDebugger.SendInternal("aPath ="); Global.mFileSystemDebugger.SendInternal(aPath); CheckInvalidPathChars(aPath); string xText = NormalizePath(aPath, false); if (aPath.Length > 0) { try { string text2 = aPath; int num = 0; while ((num < text2.Length) && (text2[num] != '?') && (text2[num] != '*')) { num++; } if (num > 0) { Path.GetFullPath(text2.Substring(0, num)); } } catch (PathTooLongException) { } catch (NotSupportedException) { } catch (ArgumentException) { } } aPath = xText; int rootLength = GetRootLength(aPath); int num2 = aPath.Length; if (num2 > rootLength) { num2 = aPath.Length; if (num2 == rootLength) { return null; } while ((num2 > rootLength) && (aPath[--num2] != Path.DirectorySeparatorChar) && (aPath[num2] != Path.AltDirectorySeparatorChar)) { } return aPath.Substring(0, num2); } } return null; } internal static int GetRootLength(string aPath) { Global.mFileSystemDebugger.SendInternal("Path.GetRootLength"); Global.mFileSystemDebugger.SendInternal("aPath ="); Global.mFileSystemDebugger.SendInternal(aPath); int i = 0; int xLength = aPath.Length; if ((xLength >= 1) && IsDirectorySeparator(aPath[0])) { i = 1; if ((xLength >= 2) && IsDirectorySeparator(aPath[1])) { i = 2; int xNum = 2; while (i < xLength) { if (((aPath[i] == Path.DirectorySeparatorChar) || (aPath[i] == Path.AltDirectorySeparatorChar)) && (--xNum <= 0)) { break; } i++; } } } else if ((xLength >= 2) && (aPath[1] == VFSManager.GetVolumeSeparatorChar())) { i = 2; if ((xLength >= 3) && IsDirectorySeparator(aPath[2])) { i++; } } return i; } public static string NormalizePath(string aPath, bool aFullCheck) { Global.mFileSystemDebugger.SendInternal("Path.NormalizePath"); if (aPath == null) { Global.mFileSystemDebugger.SendInternal("aPath is null"); throw new ArgumentNullException("aPath"); } string result = aPath; if (IsRelative(result)) { result = Directory.GetCurrentDirectory() + Path.DirectorySeparatorChar + result; Global.mFileSystemDebugger.SendInternal("aPath is relative"); Global.mFileSystemDebugger.SendInternal("aPath ="); Global.mFileSystemDebugger.SendInternal(aPath); Global.mFileSystemDebugger.SendInternal("result ="); Global.mFileSystemDebugger.SendInternal(result); } if (IsDirectorySeparator(result[result.Length - 1])) { Global.mFileSystemDebugger.SendInternal("Found directory seprator"); if (result.Length > 3) { result = result.Remove(result.Length - 1); } } Global.mFileSystemDebugger.SendInternal("aPath ="); Global.mFileSystemDebugger.SendInternal(aPath); Global.mFileSystemDebugger.SendInternal("result ="); Global.mFileSystemDebugger.SendInternal(result); return result; } } }