Skip to content

Commit 1af3963

Browse files
authored
Do not Path.Join user directory if it's "C:" (#94587)
Fixes #68503 On netfx we were concatenating user directories ending with volume separator `:` instead of joining with a path separator `\`. That is not the case in .NET [core]. This change brings that back as it is incorrect to join paths like "C:" with a separator in between the enumerated entries as the meaning of "relative to drive's CWD" gets lost.
1 parent a56efef commit 1af3963

File tree

4 files changed

+41
-1
lines changed

4 files changed

+41
-1
lines changed

src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Unix.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,5 +168,11 @@ public FileSystemInfo ToFileSystemInfo()
168168
/// </summary>
169169
public string ToFullPath() =>
170170
new string(FullPath);
171+
172+
private static string Join(
173+
ReadOnlySpan<char> originalRootDirectory,
174+
ReadOnlySpan<char> relativePath,
175+
ReadOnlySpan<char> fileName) =>
176+
Path.Join(originalRootDirectory, relativePath, fileName);
171177
}
172178
}

src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Windows.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,5 +75,18 @@ public FileSystemInfo ToFileSystemInfo()
7575
/// <returns>A string representing the full path.</returns>
7676
public string ToFullPath() =>
7777
Path.Join(Directory, FileName);
78+
79+
private static string Join(
80+
ReadOnlySpan<char> originalRootDirectory,
81+
ReadOnlySpan<char> relativePath,
82+
ReadOnlySpan<char> fileName)
83+
{
84+
if (originalRootDirectory.Length == 2 && originalRootDirectory[1] == Path.VolumeSeparatorChar)
85+
{
86+
return string.Concat(originalRootDirectory, Path.Join(relativePath, fileName));
87+
}
88+
89+
return Path.Join(originalRootDirectory, relativePath, fileName);
90+
}
7891
}
7992
}

src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public string ToSpecifiedFullPath()
3939
if (Path.EndsInDirectorySeparator(OriginalRootDirectory) && PathInternal.StartsWithDirectorySeparator(relativePath))
4040
relativePath = relativePath.Slice(1);
4141

42-
return Path.Join(OriginalRootDirectory, relativePath, FileName);
42+
return Join(OriginalRootDirectory, relativePath, FileName);
4343
}
4444
}
4545
}

src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/GetFileSystemEntries_str.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,27 @@ public void WindowsInvalidCharsPath_Core(string invalid)
246246
Assert.Throws<IOException>(() => GetEntries(invalid));
247247
}
248248

249+
[ConditionalFact(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))]
250+
[PlatformSpecific(TestPlatforms.Windows)]
251+
public void WindowsRelativeToCurrentDrivePath()
252+
{
253+
RemoteExecutor.Invoke(() =>
254+
{
255+
string testRootDir = GetTestFilePath();
256+
Directory.CreateDirectory(testRootDir);
257+
Directory.SetCurrentDirectory(testRootDir);
258+
259+
const string TestSubdir = "foo";
260+
Directory.CreateDirectory(Path.Combine(testRootDir, TestSubdir));
261+
262+
string currentDrive = testRootDir.Substring(0, 2);
263+
string[] results = GetEntries(currentDrive);
264+
265+
string result = Assert.Single(results);
266+
Assert.Equal(currentDrive + TestSubdir, result);
267+
}).Dispose();
268+
}
269+
249270
[Theory,
250271
InlineData(" "),
251272
InlineData(" "),

0 commit comments

Comments
 (0)