Following up from https://github.com/PowerShell/PowerShell/pull/13082#discussion_r466009551:
On Windows, the .Target property (an ETS property added to FileSystemInfo instances) has always returned a symlink's target _as defined in the link itself_ - which may be a relative or an absolute path.
On Unix, we currently unexpectedly resolve the target path to a _full_ path in .Target, with no ability to inspect the target path _as defined_.
Note: It would also be convenient to have a separate property that always reflects the _full_ path, irrespective of whether the symlink is defined with a relative or full target path - see #13366.
On macOS or Linux:
Push-Location Temp:/
mkdir -p f$PID
# Define a symlink with a *relative* target path.
New-Item -Type SymbolicLink f$PID_L -Target ./f$PID
# Querying .Target should return the target path *as defined*.
(Get-Item f$PID_L).Target | Should -Be ./f$PID
Remove-Item -Recurse f$PID, f$PID_L; Pop-Location
The test should succeed.
The test fails, because the target path is returned not as defined, but as a full path.
PowerShell Core 7.1.0-preview.5
There is a problem with Target property on Unix-s. We call FollowSymLink() that is a native code from PowerShell-Native (libpsl-native)
https://github.com/PowerShell/PowerShell-Native/blob/7b7b889e8a331fd0ea47082d5edbf80402ea51ad/src/libpsl-native/src/followsymlink.cpp#L39-L47
Docs explicitly say that realpath() always returns absolute path.
It is should be fixed in psl (PowerShell-Native repository) and we need an approve from @adityapatwardhan .
GitHub
Contribute to PowerShell/PowerShell-Native development by creating an account on GitHub.
@iSazonov, looks like the FollowSymLink() function needs another, optional argument that specifies whether realpath() should be called for resolution to a full path (or, alternatively, introduce a separate ReadSymLink() function).
If not, a call to readlink() is sufficient , which FollowSymLink() already does - but only _as a fallback_ (if the target path doesn't exist).
If we think about a script users will use either Target or ResolvedTarget but not both. In the case I'd add new p/invoke FollowSymLinkResolved().
I don't know whether we need this or no but if we need we could resolve the full path in C# without complication psl.
It certainly would be nice to have cross-platform realpath() functionality available in .NET itself, and to surface that via Convert-Path, as suggested in #10640 - I never got around to asking in the dotnet repo for such an API.
I never got around to asking in the dotnet repo for such an API
There is an issue to add symlink support - you can share thoughts there.
Thanks, @iSazonov, I've added a suggestion to add a System.IO.Path.GetFullPath() overload for canonical path resolution there: https://github.com/dotnet/runtime/issues/24271#issuecomment-670709364
Most helpful comment
Thanks, @iSazonov, I've added a suggestion to add a
System.IO.Path.GetFullPath()overload for canonical path resolution there: https://github.com/dotnet/runtime/issues/24271#issuecomment-670709364