aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/path.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/path.cc')
-rw-r--r--winsup/cygwin/path.cc53
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"