diff options
Diffstat (limited to 'src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs')
-rw-r--r-- | src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs b/src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs new file mode 100644 index 0000000000..bea2df93b9 --- /dev/null +++ b/src/mscorlib/corefx/System/IO/PathInternal.CaseSensitivity.cs @@ -0,0 +1,75 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; + +namespace System.IO +{ + /// <summary>Contains internal path helpers that are shared between many projects.</summary> + internal static partial class PathInternal + { + private enum Tristate : byte + { + NotInitialized, + True, + False, + } + + private static Tristate s_isCaseSensitive = Tristate.NotInitialized; + + /// <summary>Returns a comparison that can be used to compare file and directory names for equality.</summary> + internal static StringComparison StringComparison + { + get + { + return IsCaseSensitive ? + StringComparison.Ordinal : + StringComparison.OrdinalIgnoreCase; + } + } + + /// <summary>Gets whether the system is case-sensitive.</summary> + internal static bool IsCaseSensitive + { + get + { + // This must be lazily initialized as there are dependencies on PathInternal's static constructor + // being fully initialized. (GetIsCaseSensitive() calls GetFullPath() which needs to use PathInternal) + if (s_isCaseSensitive == Tristate.NotInitialized) + s_isCaseSensitive = GetIsCaseSensitive() ? Tristate.True : Tristate.False; + + return s_isCaseSensitive == Tristate.True; + } + } + + /// <summary> + /// Determines whether the file system is case sensitive. + /// </summary> + /// <remarks> + /// Ideally we'd use something like pathconf with _PC_CASE_SENSITIVE, but that is non-portable, + /// not supported on Windows or Linux, etc. For now, this function creates a tmp file with capital letters + /// and then tests for its existence with lower-case letters. This could return invalid results in corner + /// cases where, for example, different file systems are mounted with differing sensitivities. + /// </remarks> + private static bool GetIsCaseSensitive() + { + try + { + string pathWithUpperCase = Path.Combine(Path.GetTempPath(), "CASESENSITIVETEST" + Guid.NewGuid().ToString("N")); + using (new FileStream(pathWithUpperCase, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None, 0x1000, FileOptions.DeleteOnClose)) + { + string lowerCased = pathWithUpperCase.ToLowerInvariant(); + return !File.Exists(lowerCased); + } + } + catch (Exception exc) + { + // In case something goes terribly wrong, we don't want to fail just because + // of a casing test, so we assume case-insensitive-but-preserving. + Debug.Fail("Casing test failed: " + exc); + return false; + } + } + } +} |