Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: path/filepath: add a function to canonicalize paths #37113

Open
bk2204 opened this issue Feb 7, 2020 · 5 comments
Open

proposal: path/filepath: add a function to canonicalize paths #37113

bk2204 opened this issue Feb 7, 2020 · 5 comments

Comments

@bk2204
Copy link

@bk2204 bk2204 commented Feb 7, 2020

What version of Go are you using (go version)?

$ go version
go version go1.12.7 windows/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

Applies to all OSes

What did you do?

  1. Mounted a UNC path as a drive letter.
  2. In CMD, switched the current working directory to that drive.
  3. Called filepath.Abs on a relative path.
  4. Called filepath.EvalSymlinks on the result of that function.

What did you expect to see?

The same results as calling GetFinalPathNameByHandle: a UNC path.

What did you see instead?

A path using the drive letter instead of the UNC path.

Notes

This affects any attempt to canonicalize paths using the output of Git in such a situation. Git produces some paths as absolute and some paths as relative, and uses GetFinalPathNameByHandle for canonicalizing absolute paths. However, Go lacks a function to canonicalize paths in a standard way, so it isn't possible to produce results equivalent to a C program and still write code that works portably across systems.

Go should add a function that is explicitly defined to canonicalize paths in a way equivalent to the underlying operating system, since using filepath.Abs and filepath.EvalSymlinks doesn't work correctly on Windows. It does work fine on Unix, but Unix paths are much simpler and easier to reason about.

It was determined in #17084 that filepath.Abs and filepath.EvalSymlinks were sufficient in this case, but that doesn't appear to be true. I expect there are other cases in which those don't work on Windows, but I am insufficiently versed in Windows paths to know what those are.

This was originally reported to the Git LFS project in git-lfs/git-lfs#4012.

@dmitshur dmitshur changed the title Add a function to canonicalize paths path/filepath: add a function to canonicalize paths Feb 7, 2020
@dmitshur dmitshur added this to the Backlog milestone Feb 7, 2020
@dmitshur
Copy link
Member

@dmitshur dmitshur commented Feb 7, 2020

/cc @robpike @rsc per owners.

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Feb 7, 2020

What did you expect to see?

The same results as calling GetFinalPathNameByHandle: a UNC path.

I did not try it, but, I suspect, UNC paths wouldn't work in some situations. For example, can you pass UNC path to os.Chdir?

Alex

@ianlancetaylor ianlancetaylor changed the title path/filepath: add a function to canonicalize paths proposal: path/filepath: add a function to canonicalize paths Feb 7, 2020
@gopherbot gopherbot added the Proposal label Feb 7, 2020
@bk2204
Copy link
Author

@bk2204 bk2204 commented Feb 7, 2020

I don't know for certain, but judging by a quick Google search, it appears to be possible in Ruby, so I assume one can do that in C-based languages.

I'm not a Windows developer, so I'm not a good person to ask about the capabilities of Windows. I'm just a Unix developer trying to make general-purpose software not be terrible on Windows.

@alexbrainman
Copy link
Member

@alexbrainman alexbrainman commented Feb 8, 2020

I don't know for certain, but judging by a quick Google search, it appears to be possible in Ruby, so I assume one can do that in C-based languages.

You are correct. I was wrong. os.Chdir does work with UNC paths.

Alex

@bk2204
Copy link
Author

@bk2204 bk2204 commented Jun 25, 2020

It is also the case that filepath.EvalSymlinks fails to work when canonicalizing paths where there's a junction to a volume that lacks a drive letter (a OneDrive mount is a good example of this). For example, if C:\Users\User\OneDrive\Vault is a junction pointing to a OneDrive mount and we try to call filepath.EvalSymlinks("C:/Users/Users/OneDrive/Vault/home.git"), that will fail with readlink C:\Users\User\OneDrive\Vault: The system cannot find the path specified.

This also works with C-based programs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.