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

resolve() doesn't resolve intermediate symlinks on MS-Windows #4211

Closed
idbrii opened this issue Apr 4, 2019 · 10 comments
Closed

resolve() doesn't resolve intermediate symlinks on MS-Windows #4211

idbrii opened this issue Apr 4, 2019 · 10 comments

Comments

@idbrii
Copy link

idbrii commented Apr 4, 2019

:help resolve() says:

On MS-Windows, ...
When {filename} is a symbolic link or junction point, return
the full path to the target. ...

On Unix, repeat resolving symbolic links in all path
components of {filename} and return the simplified result.

resolve() should resolve all components of the path on MS-Windows like it does on Unix to make plugins more portable.

While not necessarily difficult to implement recursive resolve, it's cumbersome for every plugin to support that code.

Looks like dce1e89 (#3896) added the ability to resolve mklink-type links for files, but it doesn't work on folders within the path (but does work if the folder is the final component of the path).

Example failure:

set noshellslash
ec mkdir('c:\scratch\linktest-real')
! mklink /D c:\scratch\linktest-link c:\scratch\linktest-real
w c:\scratch\linktest-real\text.txt
ec resolve('c:\scratch\linktest-link\text.txt')
ec resolve('c:\scratch\linktest-link')

Expected:

c:\scratch\linktest-real\text.txt
c:\scratch\linktest-real

Actual:

c:\scratch\linktest-link\text.txt
c:\scratch\linktest-real

If I make link to text.txt instead, then resolve() also works as expected:

! mklink c:\scratch\linktest-real\text-link.txt c:\scratch\linktest-real\text.txt
ec resolve('c:\scratch\linktest-real\text-link.txt')

Expected and Actual:

c:\scratch\linktest-link\text.txt

Environment :

@idbrii
Copy link
Author

idbrii commented Apr 4, 2019

It looks like this can be achieved with GetFinalPathNameByHandle:

A final path is the path that is returned when a path is fully resolved. For example, for a symbolic link named "C:\tmp\mydir" that points to "D:\yourdir", the final path would be "D:\yourdir".

GetFinalPathNameByHandle is first available in Windows Vista, but symbolic links were also first available with Windows Vista.

@idbrii
Copy link
Author

idbrii commented Apr 4, 2019

I mistakenly forgot /D when linking my directory which caused resolve to fail for links as the last component of a path. Links within the path still fail to resolve.

I updated the original issue text.

@idbrii idbrii changed the title resolve() doesn't resolve directories on MS-Windows resolve() doesn't resolve intermediate symlinks on MS-Windows Apr 4, 2019
@k-takata
Copy link
Member

Removing this check will fix the problem:

vim/src/os_mswin.c

Lines 1790 to 1794 in b58a4b9

if ((GetFileAttributesW(p) & FILE_ATTRIBUTE_REPARSE_POINT) == 0)
{
vim_free(p);
goto fail;
}

However, I'm not sure this doesn't cause another issue.
What do you think @mattn?

@mattn
Copy link
Member

mattn commented May 28, 2019

I checkd with removing the part of code. Seems good to me.

@k-takata
Copy link
Member

Looking at your PR #3896 again, the tests seem to fail without the check of the attribute:
https://ci.appveyor.com/project/chrisbra/vim/builds/22096039/job/8f27n0h9vee8n9oq

@k-takata
Copy link
Member

Ah, the problem might be solved with the commit e17c269.
@mattn Have you checked whether the all tests pass with removing the part of code?

@zdm
Copy link

zdm commented Jun 21, 2019

This issue is appears again in the last patches, after 1416.
Please, fix it.

@mattn
Copy link
Member

mattn commented Jun 21, 2019

This issue is tested on master branch.

call assert_equal('Xdir/text.txt', resolve('Xdir/text.txt'))
call assert_equal(s:normalize_fname(getcwd() . '\Xdir\text.txt'), s:normalize_fname(resolve('Xdirlink\text.txt')))
call assert_equal(s:normalize_fname(getcwd() . '\Xdir'), s:normalize_fname(resolve('Xdirlink')))

Maybe, your case is different from this.

@zdm
Copy link

zdm commented Jun 21, 2019

"Signify" plugin stop worked again on windows after patch 1416, developers told me, that the problem is in reparse point or related.

@chrisbra
Copy link
Member

@zdm Well, first thing would be trying to figure out an exact test case that fails for you. If I remember correctly you are not using reparse points, so I am wondering why you saw those failures. Please try to come up with a minimal reproducible test case and open a new ticket. Thanks.

manuelschiller pushed a commit to manuelschiller/vim that referenced this issue Nov 10, 2019
… of path

Problem:    MS-Windows: resolve() does not resolve all components of the path.
            (David Briscoe)
Solution:   Do not bail out for a reparse point. (Yasuhiro Matsumoto,
            closes vim#4211, closes vim#4447)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants