aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorerw7 <erw7.github@gmail.com>2020-03-27 16:07:39 +0900
committererw7 <erw7.github@gmail.com>2020-04-02 21:13:18 +0900
commitb687a6c2b2c096a68b46141947aef29c616f7a1f (patch)
treee8427fb1521b4fd03a246a6e5e6be48801cc7610 /src
parentf61331e184d8db6d8dc965856eba1db321a2d8f3 (diff)
downloadrneovim-b687a6c2b2c096a68b46141947aef29c616f7a1f.tar.gz
rneovim-b687a6c2b2c096a68b46141947aef29c616f7a1f.tar.bz2
rneovim-b687a6c2b2c096a68b46141947aef29c616f7a1f.zip
Change to canonicalize only when reparse point in included
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval/funcs.c4
-rw-r--r--src/nvim/os/fs.c45
2 files changed, 48 insertions, 1 deletions
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index b4a3e29156..68eca56235 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -6711,7 +6711,9 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr)
#ifdef WIN32
char *v = os_resolve_shortcut(fname);
if (v == NULL) {
- v = os_realpath(fname, v);
+ if (os_is_reparse_point_include(fname)) {
+ v = os_realpath(fname, v);
+ }
}
rettv->vval.v_string = (char_u *)(v == NULL ? xstrdup(fname) : v);
#else
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index e06762383f..873b611151 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -1257,4 +1257,49 @@ shortcut_end:
return rfname;
}
+#define is_path_sep(c) ((c) == L'\\' || (c) == L'/')
+/// Returns true if the path contains a reparse point (junction or symbolic
+/// link). Otherwise false in returned.
+bool os_is_reparse_point_include(const char *path)
+{
+ wchar_t *p, *q, *utf16_path;
+ wchar_t buf[MAX_PATH];
+ DWORD attr;
+ bool result = false;
+
+ const int r = utf8_to_utf16(path, -1, &utf16_path);
+ if (r != 0) {
+ EMSG2("utf8_to_utf16 failed: %d", r);
+ return false;
+ }
+
+ p = utf16_path;
+ if (isalpha(p[0]) && p[1] == L':' && is_path_sep(p[2])) {
+ p += 3;
+ } else if (is_path_sep(p[0]) && is_path_sep(p[1])) {
+ p += 2;
+ }
+
+ while (*p != L'\0') {
+ q = wcspbrk(p, L"\\/");
+ if (q == NULL) {
+ p = q = utf16_path + wcslen(utf16_path);
+ } else {
+ p = q + 1;
+ }
+ if (q - utf16_path >= MAX_PATH) {
+ break;
+ }
+ wcsncpy(buf, utf16_path, (size_t)(q - utf16_path));
+ buf[q - utf16_path] = L'\0';
+ attr = GetFileAttributesW(buf);
+ if (attr != INVALID_FILE_ATTRIBUTES
+ && (attr & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
+ result = true;
+ break;
+ }
+ }
+ xfree(utf16_path);
+ return result;
+}
#endif