diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 34e4b01d4a..dbd80ceaa6 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -2251,6 +2251,13 @@ namespace Microsoft.PowerShell.Commands } else { + // for hardlinks we resolve the target to an absolute path + if (!IsAbsolutePath(strTargetPath)) + { + // there is already a check before here so that strTargetPath should only resolve to 1 path + strTargetPath = SessionState.Path.GetResolvedPSPathFromPSPath(strTargetPath).FirstOrDefault()?.Path; + } + exists = GetFileSystemInfo(strTargetPath, out isDirectory) != null; } } @@ -2293,6 +2300,13 @@ namespace Microsoft.PowerShell.Commands if (Force) { + if (itemType == ItemType.HardLink && string.Equals(path, strTargetPath, StringComparison.OrdinalIgnoreCase)) + { + string message = StringUtil.Format(FileSystemProviderStrings.NewItemTargetIsSameAsLink, path); + WriteError(new ErrorRecord(new InvalidOperationException(message), "TargetIsSameAsLink", ErrorCategory.InvalidOperation, path)); + return; + } + try { if (!isSymLinkDirectory && symLinkExists) diff --git a/src/System.Management.Automation/resources/FileSystemProviderStrings.resx b/src/System.Management.Automation/resources/FileSystemProviderStrings.resx index 894fe5f6af..436e03df32 100644 --- a/src/System.Management.Automation/resources/FileSystemProviderStrings.resx +++ b/src/System.Management.Automation/resources/FileSystemProviderStrings.resx @@ -328,7 +328,7 @@ Maximum size for drive has been exceeded: {0}. - Cannot create symbolic link because the path {0} already exists. + Cannot create link because the path already exists: {0}. Skip already-visited directory {0}. @@ -336,4 +336,7 @@ Destination path cannot be a subdirectory of the source: {0}. + + The target and path cannot be the same. + diff --git a/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 index bec4ad83b8..5e55630c06 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Management/FileSystem.Tests.ps1 @@ -600,6 +600,24 @@ Describe "Hard link and symbolic link tests" -Tags "CI", "RequireAdminOnWindows" New-Item -ItemType Junction -Path $junctionToDir -Value $realDir > $null Test-Path $junctionToDir | Should -BeTrue } + + It 'New-Item can create hardlink with relative path' { + try { + Push-Location $TestDrive + 1 > 1.txt + New-Item -ItemType HardLink -Path 2.txt -Target 1.txt -ErrorAction Stop + $hl = Get-Item -Path .\2.txt -ErrorAction Stop + $hl.LinkType | Should -BeExactly "HardLink" + } + finally { + Pop-Location + } + } + + It 'New-Item will fail to forcibly create hardlink to itself' { + $i = New-Item -ItemType File -Path "$TestDrive\file.txt" -Force -ErrorAction Ignore + { New-Item -ItemType HardLink -Path $i -Target $i -Force -ErrorAction Stop } | Should -Throw -ErrorId "TargetIsSameAsLink,Microsoft.PowerShell.Commands.NewItemCommand" + } } Context "Get-ChildItem and symbolic links" {