Cygwin: realpath: fix cygwin installation dir being access via junction

Consider this case:

- Cygwin installed in C:\cygwin64

- mklink /j D:\cygwin64 C:\cygwin64

- create testcase calling

    realpath("/", result);
    printf ("%s\n", result);

- start cmd

    >C:\cygwin64\bin\bash -lc <path-to-testcase>
    /
    >D\cygwin64\bin\bash -lc <path-to-testcase>
    /cygdrive/c/cygwin64

This scenario circumventing the mount point handling which is automated
in terms of /, depending on the path returned from GetModuleFileNameW
for the Cygwin DLL.  When calling D:\cygwin64\bin\bash the dir returned
from GetModuleFileNameW is D:\cygwin64\bin, thus root is D:\cygwin64.

However, junctions are treated as symlinks in Cygwin which explains why
the path gets converted to a cygdrive path.

Fix this by calling GetFinalPathNameByHandleW on the result from
GetModuleFileNameW to get the correct root path, even if accessed via
a junction point.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2021-02-19 18:15:58 +01:00
parent 543e39bb12
commit 6d898f43fc
1 changed files with 13 additions and 0 deletions

View File

@ -144,6 +144,19 @@ init_cygheap::init_installation_root ()
api_fatal ("Can't initialize Cygwin installation root dir.\n"
"GetModuleFileNameW(%p, %p, %u), %E",
cygwin_hmodule, installation_root_buf, PATH_MAX);
/* We don't care if fetching the final pathname fails, it's non-fatal and
the path returned by GetModuleFileNameW is still valid. */
HANDLE h;
h = CreateFileW (installation_root_buf, GENERIC_READ, FILE_SHARE_VALID_FLAGS,
&sec_none, OPEN_EXISTING, 0, 0);
if (h != INVALID_HANDLE_VALUE)
{
GetFinalPathNameByHandleW (h, installation_root_buf, PATH_MAX,
FILE_NAME_NORMALIZED);
CloseHandle (h);
}
PWCHAR p = installation_root_buf;
if (wcsncasecmp (p, L"\\\\", 2)) /* Normal drive letter path */
{