Fix path issues (#16554)
authorJeremy Kuhne <jeremy.kuhne@microsoft.com>
Sun, 25 Feb 2018 16:16:25 +0000 (08:16 -0800)
committerJan Kotas <jkotas@microsoft.com>
Sun, 25 Feb 2018 16:16:25 +0000 (08:16 -0800)
Path tests weren't running so a few issues sneaked in.

src/mscorlib/shared/System/IO/Path.cs
src/mscorlib/shared/System/IO/PathHelper.Windows.cs
src/mscorlib/shared/System/IO/PathInternal.Windows.cs

index 7685099..586ddf3 100644 (file)
@@ -79,7 +79,7 @@ namespace System.IO
         /// </remarks>
         public static string GetDirectoryName(string path)
         {
-            if (PathInternal.IsEffectivelyEmpty(path))
+            if (path == null || PathInternal.IsEffectivelyEmpty(path))
                 return null;
 
             int end = GetDirectoryNameOffset(path);
index dda9b2c..039a288 100644 (file)
@@ -203,6 +203,9 @@ namespace System.IO
                 }
             }
 
+            // Need to trim out the trailing separator in the input builder
+            inputBuilder.Length = inputBuilder.Length - 1;
+
             // If we were able to expand the path, use it, otherwise use the original full path result
             ref ValueStringBuilder builderToUse = ref (success ? ref outputBuilder : ref inputBuilder);
 
index 95bd062..433d6b6 100644 (file)
@@ -130,6 +130,19 @@ namespace System.IO
         }
 
         /// <summary>
+        /// Returns true if the path is a device UNC (\\?\UNC\, \\.\UNC\)
+        /// </summary>
+        internal static bool IsDeviceUNC(ReadOnlySpan<char> path)
+        {
+            return path.Length >= UncExtendedPrefixLength
+                && IsDevice(path)
+                && IsDirectorySeparator(path[7])
+                && path[4] == 'U'
+                && path[5] == 'N'
+                && path[6] == 'C';
+        }
+
+        /// <summary>
         /// Returns true if the path uses the canonical form of extended syntax ("\\?\" or "\??\"). If the
         /// path matches exactly (cannot use alternate directory separators) Windows will skip normalization
         /// and path length checks.
@@ -178,12 +191,12 @@ namespace System.IO
             int volumeSeparatorLength = 2;  // Length to the colon "C:"
             int uncRootLength = 2;          // Length to the start of the server name "\\"
 
-            bool extendedSyntax = StartsWithOrdinal(path, ExtendedPathPrefix);
-            bool extendedUncSyntax = StartsWithOrdinal(path, UncExtendedPathPrefix);
-            if (extendedSyntax)
+            bool deviceSyntax = IsDevice(path);
+            bool deviceUnc = deviceSyntax && IsDeviceUNC(path);
+            if (deviceSyntax)
             {
                 // Shift the position we look for the root from to account for the extended prefix
-                if (extendedUncSyntax)
+                if (deviceUnc)
                 {
                     // "\\" -> "\\?\UNC\"
                     uncRootLength = UncExtendedPathPrefix.Length;
@@ -195,12 +208,12 @@ namespace System.IO
                 }
             }
 
-            if ((!extendedSyntax || extendedUncSyntax) && pathLength > 0 && IsDirectorySeparator(path[0]))
+            if ((!deviceSyntax || deviceUnc) && pathLength > 0 && IsDirectorySeparator(path[0]))
             {
                 // UNC or simple rooted path (e.g. "\foo", NOT "\\?\C:\foo")
 
                 i = 1; //  Drive rooted (\foo) is one character
-                if (extendedUncSyntax || (pathLength > 1 && IsDirectorySeparator(path[1])))
+                if (deviceUnc || (pathLength > 1 && IsDirectorySeparator(path[1])))
                 {
                     // UNC (\\?\UNC\ or \\), scan past the next two directory separators at most
                     // (e.g. to \\?\UNC\Server\Share or \\Server\Share\)