Skip to content

Commit b18eaca

Browse files
authored
Resolve symbolic link target relative to the symbolic link instead of the working directory (PowerShell#15235) (PowerShell#20943)
1 parent c24e8e4 commit b18eaca

2 files changed

Lines changed: 39 additions & 8 deletions

File tree

src/System.Management.Automation/namespaces/FileSystemProvider.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2258,16 +2258,14 @@ protected override void NewItem(
22582258
{
22592259
exists = true;
22602260

2261-
var normalizedTargetPath = strTargetPath;
2262-
if (strTargetPath.StartsWith(".\\", StringComparison.OrdinalIgnoreCase) ||
2263-
strTargetPath.StartsWith("./", StringComparison.OrdinalIgnoreCase))
2264-
{
2265-
normalizedTargetPath = Path.Join(SessionState.Internal.CurrentLocation.ProviderPath, strTargetPath.AsSpan(2));
2266-
}
2261+
// unify directory separators to be consistent with the rest of PowerShell even on non-Windows platforms;
2262+
// do this before resolving the target, otherwise e.g. `.\test` would break on Linux, since the combined
2263+
// path below would be something like `/path/to/cwd/.\test`
2264+
strTargetPath = strTargetPath.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator);
22672265

2266+
// check if the target is a file or directory
2267+
var normalizedTargetPath = Path.Combine(Path.GetDirectoryName(path), strTargetPath);
22682268
GetFileSystemInfo(normalizedTargetPath, out isDirectory);
2269-
2270-
strTargetPath = strTargetPath.Replace(StringLiterals.AlternatePathSeparator, StringLiterals.DefaultPathSeparator);
22712269
}
22722270
else
22732271
{

test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
# Copyright (c) Microsoft Corporation.
22
# Licensed under the MIT License.
3+
4+
Import-Module HelpersCommon
5+
36
Describe "Basic FileSystem Provider Tests" -Tags "CI" {
47
BeforeAll {
58
$testDir = "TestDir"
@@ -621,6 +624,11 @@ Describe "Hard link and symbolic link tests" -Tags "CI", "RequireAdminOnWindows"
621624
}
622625

623626
Context "New-Item and hard/symbolic links" {
627+
AfterEach {
628+
# clean up created links after each test
629+
Remove-Item -Exclude (Split-Path -Leaf $realFile, $realDir, $realDir2) -Recurse $TestPath/*
630+
}
631+
624632
It "New-Item can create a hard link to a file" {
625633
New-Item -ItemType HardLink -Path $hardLinkToFile -Value $realFile > $null
626634
Test-Path $hardLinkToFile | Should -BeTrue
@@ -664,6 +672,31 @@ Describe "Hard link and symbolic link tests" -Tags "CI", "RequireAdminOnWindows"
664672
$link.LinkType | Should -BeExactly "SymbolicLink"
665673
$link.Target | Should -BeExactly $real.ToString()
666674
}
675+
676+
It "New-Item can create a directory symbolic link to a directory using a relative path" -Skip:(-Not $IsWindows) {
677+
$target = Split-Path -Leaf $realDir
678+
New-Item -ItemType SymbolicLink -Path $symLinkToDir -Value $target > $null
679+
Test-Path $symLinkToDir | Should -BeTrue
680+
$real = Get-Item -Path $realDir
681+
$link = Get-Item -Path $symLinkToDir
682+
$link | Should -BeOfType System.IO.DirectoryInfo
683+
$link.LinkType | Should -BeExactly "SymbolicLink"
684+
$link.ResolvedTarget | Should -BeExactly $real.ToString()
685+
$link.Target | Should -BeExactly $target
686+
}
687+
688+
It "New-Item can create a directory symbolic link to a directory using a relative path with .\" -Skip:(-Not $IsWindows) {
689+
$target = ".\$(Split-Path -Leaf $realDir)"
690+
New-Item -ItemType SymbolicLink -Path $symLinkToDir -Value $target > $null
691+
Test-Path $symLinkToDir | Should -BeTrue
692+
$real = Get-Item -Path $realDir
693+
$link = Get-Item -Path $symLinkToDir
694+
$link | Should -BeOfType System.IO.DirectoryInfo
695+
$link.LinkType | Should -BeExactly "SymbolicLink"
696+
$link.ResolvedTarget | Should -BeExactly $real.ToString()
697+
$link.Target | Should -BeExactly $target
698+
}
699+
667700
It "New-Item can create a directory junction to a directory" -Skip:(-Not $IsWindows) {
668701
New-Item -ItemType Junction -Path $junctionToDir -Value $realDir > $null
669702
Test-Path $junctionToDir | Should -BeTrue

0 commit comments

Comments
 (0)