Cygwin: symlinks: fix WSL symlinks pointing to /mnt

Commit 4a36897af3 allowed to convert /mnt/<drive> path
prefixes to Cygwin cygdrive prefixes on the fly.  However,
the patch neglected WSL symlinks pointing to the /mnt
directory.  Rearrange path conversion so /mnt is converted
to the cygdrive prefix path itself.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2020-04-02 22:25:55 +02:00 committed by Ken Brown
parent c2a4b866db
commit 2aa47e7d12
1 changed files with 35 additions and 15 deletions

View File

@ -2466,32 +2466,52 @@ check_reparse_point_target (HANDLE h, bool remote, PREPARSE_DATA_BUFFER rp,
PREPARSE_LX_SYMLINK_BUFFER rpl = (PREPARSE_LX_SYMLINK_BUFFER) rp;
char *path_buf = rpl->LxSymlinkReparseBuffer.PathBuffer;
DWORD path_len = rpl->ReparseDataLength - sizeof (DWORD);
bool full_path = false;
const size_t drv_prefix_len = strlen ("/mnt");
PBYTE utf16_ptr;
PWCHAR utf16_buf;
int utf16_bufsize;
bool full_path = false;
const size_t drv_prefix_len = strlen ("/mnt");
/* 0-terminate path_buf for easier testing. */
path_buf[path_len] = '\0';
if (path_prefix_p ("/mnt", path_buf, drv_prefix_len, false))
{
size_t len = strlen (path_buf);
if (len <= drv_prefix_len + 1)
{
/* /mnt or /mnt/. Replace with cygdrive prefix. */
stpcpy (path_buf, mount_table->cygdrive);
path_len = mount_table->cygdrive_len;
if (len == drv_prefix_len)
{
path_buf[mount_table->cygdrive_len - 1] = '\0';
--path_len;
}
rp->ReparseDataLength = path_len + sizeof (DWORD);
}
else if (islower (path_buf[drv_prefix_len + 1])
&& (path_len == drv_prefix_len + 2
|| path_buf[drv_prefix_len + 2] == '/'))
{
/* Skip forward to the slash leading the drive letter.
That leaves room for adding the colon. */
path_buf += drv_prefix_len;
path_len -= drv_prefix_len;
full_path = true;
}
}
/* Compute buffer for path converted to UTF-16. */
utf16_ptr = (PBYTE) rpl + sizeof (REPARSE_LX_SYMLINK_BUFFER)
+ rp->ReparseDataLength;
/* Skip \0-termination added above. */
++utf16_ptr;
/* Make sure pointer is aligned */
while ((intptr_t) utf16_ptr % sizeof (WCHAR))
++utf16_ptr;
utf16_buf = (PWCHAR) utf16_ptr;
utf16_bufsize = NT_MAX_PATH - (utf16_buf - (PWCHAR) rpl);
/* Check for abs path /mnt/x. Convert to x: after conversion to UTF-16. */
if (path_len >= drv_prefix_len + 2
&& !strncmp (path_buf, "/mnt/", drv_prefix_len + 1)
&& islower (path_buf[drv_prefix_len + 1])
&& (path_len == drv_prefix_len + 2
|| path_buf[drv_prefix_len + 2] == '/'))
{
/* Skip forward to the slash leading the drive letter. That leaves
room for adding the colon. */
path_buf += drv_prefix_len;
path_len -= drv_prefix_len;
full_path = true;
}
/* Now convert path to UTF-16. */
utf16_bufsize = MultiByteToWideChar (CP_UTF8, 0, path_buf, path_len,
utf16_buf, utf16_bufsize);
if (utf16_bufsize)