Skip to content

Proposed API for canonical paths #23871

Open
@carlreinke

Description

@carlreinke

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 to C:\ProgramData then the canonical form of C:\Users\All Users\..\foo is C:\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 \\.\.
  • 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 with bool.
  • Split out dotnet/corefx#25569

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-suggestionEarly API idea and discussion, it is NOT ready for implementationarea-System.IO

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions