Hi Takashi, On Dec 9 17:17, Takashi Yano wrote: > - The last change in path.cc introduced a bug that causes an error > when accessing a virtual drive which mounts UNC path such as > "\\server\share\dir" rather than "\\server\share". This patch > fixes the issue. > --- > winsup/cygwin/path.cc | 50 +++++++++++++++++++++++++------------------ > 1 file changed, 29 insertions(+), 21 deletions(-) > > diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc > index eb1255849..6682d2a58 100644 > --- a/winsup/cygwin/path.cc > +++ b/winsup/cygwin/path.cc > @@ -3507,29 +3507,37 @@ restart: > if (RtlEqualUnicodePathPrefix (&fpath, &ro_u_uncp, TRUE) > && !RtlEqualUnicodePathPrefix (&upath, &ro_u_uncp, TRUE)) > { > - /* ...get the remote path from the volume path name, > - replace remote path with drive letter, check again. */ > + /* ...get the remote path, replace remote path > + with drive letter, check again. */ > + WCHAR drive[3] = > + {(WCHAR) towupper (upath.Buffer[4]), L':', L'\0'}; > WCHAR remote[MAX_PATH]; > > - fpbuf[1] = L'\\'; > - BOOL r = GetVolumePathNameW (fpbuf, remote, MAX_PATH); > - fpbuf[1] = L'?'; > - if (r) > - { > - int remlen = wcslen (remote); > - if (remote[remlen - 1] == L'\\') > - remlen--; > - /* Hackfest */ > - fpath.Buffer[4] = upath.Buffer[4]; /* Drive letter */ > - fpath.Buffer[5] = L':'; > - WCHAR *to = fpath.Buffer + 6; > - WCHAR *from = to + remlen - 6; > - memmove (to, from, > - (wcslen (from) + 1) * sizeof (WCHAR)); > - fpath.Length -= (from - to) * sizeof (WCHAR); > - if (RtlEqualUnicodeString (&upath, &fpath, !!ci_flag)) > - goto file_not_symlink; > - } > + if (!QueryDosDeviceW (drive, remote, MAX_PATH)) > + goto file_not_symlink; /* fallback */ > + > + int remlen = wcslen (remote);
QueryDosDeviceW returns the string followed by two \0 chars, and that's reflected by its return value. You could skip the wcslen call: int remlen; remlen = QueryDosDeviceW (drive, remote, MAX_PATH); if (!remlen) goto file_not_symlink; remlen -= 2; > + if (remote[remlen - 1] == L'\\') > + remlen--; > + WCHAR *p; > + if (wcsstr (remote, L"\\??\\UNC\\") == remote) That should be wcsncmp. The subst'ed UNC path always begins with that string. Alternatively: UNICODE_STRING rpath; RtlInitCountedUnicodeString (&rpath, remote, remlen * sizeof (WCHAR)); if (RtlEqualUnicodePathPrefix (&rpath, &ro_u_uncp, TRUE)) > + remlen -= 6; > + else if ((p = wcschr (remote, L';') + 1) This expression is always true, even if wcschr returns a NULL pointer. > + && wcsstr (p, drive) == p && wcsncmp (p, drive, 2) == 2? Alternatively just skip the additional drive letter check and move the pointer immediately forward to the next backslash: > + && (p = wcschr (p + 2, L'\\'))) > + remlen -= p - remote - 1; > + else > + goto file_not_symlink; /* fallback */ > + /* Hackfest */ > + fpath.Buffer[4] = drive[0]; /* Drive letter */ > + fpath.Buffer[5] = L':'; > + WCHAR *to = fpath.Buffer + 6; > + WCHAR *from = to + remlen; > + memmove (to, from, > + (wcslen (from) + 1) * sizeof (WCHAR)); > + fpath.Length -= (from - to) * sizeof (WCHAR); > + if (RtlEqualUnicodeString (&upath, &fpath, !!ci_flag)) > + goto file_not_symlink; > } > issymlink = true; > /* upath.Buffer is big enough and unused from this point on. > -- > 2.34.1 Thanks, Corinna