Description
Rationale
"It seems we need a new API that allows us to get the canonical path that hits the disk and follows links and fixes casing" —API Review 2015-08-27
Proposed API
public static class Path
{
public static string GetCanonicalPath( string path ); // Resolves symbolic links
public static string GetCanonicalPath( string path, bool preserveSymbolicLinks );
}
Details
A canonical path
- is a fully qualified path path,
- uses only
DirectorySeparatorChar
as a directory separator, - has no trailing directory separator (unless it is a/the root),
- contains no navigation elements (
.
and..
) and no empty path elements (ex./foo//bar
), - contains no symbolic links (unless otherwise specified),
- has its root in a canonical form (ex. on Windows, drive letters will be upper case), and
- adopts the actual casing of the file and directory names if the file and directory names are case-insensitive.
The behavior of ..
with respect to symbolic links is platform dependent. On Windows, it removes the symbolic link element. On Linux, it removes an element of path that was resolved from the symbolic link.
Examples:
- Windows: If
C:\Users\All Users
is a symbolic link toC:\ProgramData
then the canonical form ofC:\Users\All Users\..\foo
isC:\Users\foo
. - Linux: If
/var/lock
is a symbolic link to/run/lock
then the canonical form of/var/lock/../foo
is/run/foo
.
On Linux it is not always possible to preserve symbolic links while simplifying ..
. In these cases Path.GetCanonicalPath(string, bool)
will resolve the symbolic link regardless of the value of preserveSymbolicLinks
.
For the purposes of this API, NTFS Junction Points are considered to be like Linux bind mounts and are not considered to be symbolic links.
Since most of the members of Path
do not do I/O there might be some objection to adding GetCanonicalPath
to Path
. There is at least one existing method that does do I/O — Path.GetTempFileName
— so it would not be the first.
Open Questions
- How should
GetCanonicalPath
handle paths in\\?\
and\\.\
?- Maybe return a
\\?\
path if and only if the input path was in\\?\
. - Maybe reject paths in
\\.\
.
- Maybe return a
- What should
GetCanonicalPath
do if the path does not exist?- Maybe canonicalize the existing part and append the rest as canonicalized as possible.
- Does Linux provide a mechanism for determining the actual casing of a file or directory name for files and directories that reside on a file system that is mounted in a case-insensitive mode? If it doesn't then the provided casing will have to be returned.
Related Issues
See Also
Updates
- Replace
SymbolicLinkOption
withbool
. - Split out dotnet/corefx#25569