diff options
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r-- | winsup/cygwin/path.cc | 53 |
1 files changed, 41 insertions, 12 deletions
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 3a5e2ee..310876b 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1855,9 +1855,18 @@ symlink_native (const char *oldpath, path_conv &win32_newpath) while (towupper (*++c_old) == towupper (*++c_new)) ; /* The last component could share a common prefix, so make sure we end - up on the first char after the last common backslash. */ - while (c_old[-1] != L'\\') - --c_old, --c_new; + up on the first char after the last common backslash. + + However, if c_old is a strict prefix of c_new (at a component + boundary), or vice versa, then do not try to find the last common + backslash. */ + if ((!*c_old || *c_old == L'\\') && (!*c_new || *c_new == L'\\')) + c_old += !!*c_old, c_new += !!*c_new; + else + { + while (c_old[-1] != L'\\') + --c_old, --c_new; + } /* 2. Check if prefix is long enough. The prefix must at least points to a complete device: \\?\X:\ or \\?\UNC\server\share\ are the minimum @@ -1882,8 +1891,10 @@ symlink_native (const char *oldpath, path_conv &win32_newpath) final_oldpath = &final_oldpath_buf; final_oldpath->Buffer = tp.w_get (); PWCHAR e_old = final_oldpath->Buffer; - while (num-- > 0) - e_old = wcpcpy (e_old, L"..\\"); + while (num > 1 || (num == 1 && *c_old)) + e_old = wcpcpy (e_old, L"..\\"), num--; + if (num > 0) + e_old = wcpcpy (e_old, L".."); wcpcpy (e_old, c_old); } } @@ -3911,6 +3922,7 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to, int how = what & CCP_CONVFLAGS_MASK; what &= CCP_CONVTYPE_MASK; int ret = -1; + bool prependglobalroot = false; __try { @@ -4019,7 +4031,7 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to, { /* Device name points to somewhere else in the NT namespace. Use GLOBALROOT prefix to convert to Win32 path. */ - to = (void *) wcpcpy ((wchar_t *) to, ro_u_globalroot.Buffer); + prependglobalroot = true; lsiz += ro_u_globalroot.Length / sizeof (WCHAR); } /* TODO: Same ".\\" band-aid as in CCP_POSIX_TO_WIN_A case. */ @@ -4075,6 +4087,8 @@ cygwin_conv_path (cygwin_conv_path_t what, const void *from, void *to, stpcpy ((char *) to, buf); break; case CCP_POSIX_TO_WIN_W: + if (prependglobalroot) + to = (void *) wcpcpy ((PWCHAR) to, ro_u_globalroot.Buffer); wcpcpy ((PWCHAR) to, path); break; } @@ -4495,21 +4509,36 @@ fcwd_access_t ** find_fast_cwd_pointer_x86_64 (); #endif +fcwd_access_t ** +find_fast_cwd_pointer_aarch64 (); + static fcwd_access_t ** find_fast_cwd () { fcwd_access_t **f_cwd_ptr; - /* First check if we're running on an ARM64 system. Skip - fetching FAST_CWD pointer as long as there's no solution for finding - it on that system. */ - if (wincap.host_machine () == IMAGE_FILE_MACHINE_ARM64) - return NULL; + switch (wincap.host_machine ()) + { + case IMAGE_FILE_MACHINE_ARM64: + f_cwd_ptr = find_fast_cwd_pointer_aarch64 (); + break; +#ifdef __x86_64__ + case IMAGE_FILE_MACHINE_AMD64: + f_cwd_ptr = find_fast_cwd_pointer_x86_64 (); + break; +#endif + default: + small_printf ("Cygwin WARNING:\n" +" Couldn't compute FAST_CWD pointer for an unknown architecture (%04y)\n" +" Please update to the latest available Cygwin version from\n" +" https://cygwin.com/. If the problem persists, please see\n" +" https://cygwin.com/problems.html\n\n", (int) wincap.host_machine ()); + return NULL; + } /* Fetch the pointer but don't set the global fast_cwd_ptr yet. First we have to make sure we know the version of the FAST_CWD structure used on the system. */ - f_cwd_ptr = find_fast_cwd_pointer_x86_64 (); if (!f_cwd_ptr) small_printf ("Cygwin WARNING:\n" " Couldn't compute FAST_CWD pointer. This typically occurs if you're using\n" |