Cygwin: symlinks: support WSL symlinks
Treat WSL symlinks just like other symlinks. Convert absolute paths pointing to Windows drives via /mnt/<driveletter> to Windows-style paths <driveletter>: Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
parent
f2b68dd7de
commit
31c3c0e306
|
@ -2360,6 +2360,29 @@ check_reparse_point_string (PUNICODE_STRING subst)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef IO_REPARSE_TAG_LX_SYMLINK
|
||||||
|
#define IO_REPARSE_TAG_LX_SYMLINK (0xa000001d)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct _REPARSE_LX_SYMLINK_BUFFER
|
||||||
|
{
|
||||||
|
DWORD ReparseTag;
|
||||||
|
WORD ReparseDataLength;
|
||||||
|
WORD Reserved;
|
||||||
|
struct {
|
||||||
|
DWORD FileType; /* Take member name with a grain of salt. Value is
|
||||||
|
apparently always 2 for symlinks. */
|
||||||
|
char PathBuffer[1];/* POSIX path as given to symlink(2).
|
||||||
|
Path is not \0 terminated.
|
||||||
|
Length is ReparseDataLength - sizeof (FileType).
|
||||||
|
Always UTF-8.
|
||||||
|
Chars given in incompatible codesets, e. g. umlauts
|
||||||
|
in ISO-8859-x, are converted to the Unicode
|
||||||
|
REPLACEMENT CHARACTER 0xfffd == \xef\xbf\bd */
|
||||||
|
} LxSymlinkReparseBuffer;
|
||||||
|
} REPARSE_LX_SYMLINK_BUFFER,*PREPARSE_LX_SYMLINK_BUFFER;
|
||||||
|
|
||||||
|
|
||||||
/* Return values:
|
/* Return values:
|
||||||
<0: Negative errno.
|
<0: Negative errno.
|
||||||
0: No symlink.
|
0: No symlink.
|
||||||
|
@ -2434,6 +2457,56 @@ check_reparse_point_target (HANDLE h, bool remote, PREPARSE_DATA_BUFFER rp,
|
||||||
if (check_reparse_point_string (psymbuf))
|
if (check_reparse_point_string (psymbuf))
|
||||||
return PATH_SYMLINK | PATH_REP;
|
return PATH_SYMLINK | PATH_REP;
|
||||||
}
|
}
|
||||||
|
else if (rp->ReparseTag == IO_REPARSE_TAG_LX_SYMLINK)
|
||||||
|
{
|
||||||
|
/* WSL symlink. Problem: We have to convert the path to UTF-16 for
|
||||||
|
the caller. Reparse points are 16K max. The buffer given to rp
|
||||||
|
is 32K. So there's enough trailing space in the buffer to convert
|
||||||
|
to UTF-16 and let psymbuf point to it. */
|
||||||
|
PREPARSE_LX_SYMLINK_BUFFER rpl = (PREPARSE_LX_SYMLINK_BUFFER) rp;
|
||||||
|
char *path_buf = rpl->LxSymlinkReparseBuffer.PathBuffer;
|
||||||
|
DWORD path_len = rpl->ReparseDataLength - sizeof (DWORD);
|
||||||
|
PBYTE utf16_ptr;
|
||||||
|
PWCHAR utf16_buf;
|
||||||
|
int utf16_bufsize;
|
||||||
|
bool full_path = false;
|
||||||
|
const size_t drv_prefix_len = strlen ("/mnt");
|
||||||
|
|
||||||
|
/* Compute buffer for path converted to UTF-16. */
|
||||||
|
utf16_ptr = (PBYTE) rpl + sizeof (REPARSE_LX_SYMLINK_BUFFER)
|
||||||
|
+ rp->ReparseDataLength;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
utf16_bufsize = MultiByteToWideChar (CP_UTF8, 0, path_buf, path_len,
|
||||||
|
utf16_buf, utf16_bufsize);
|
||||||
|
if (utf16_bufsize)
|
||||||
|
{
|
||||||
|
if (full_path)
|
||||||
|
{
|
||||||
|
utf16_buf[0] = utf16_buf[1]; /* Move drive letter to front */
|
||||||
|
utf16_buf[1] = L':'; /* Add colon */
|
||||||
|
}
|
||||||
|
RtlInitCountedUnicodeString (psymbuf, utf16_buf,
|
||||||
|
utf16_bufsize * sizeof (WCHAR));
|
||||||
|
return PATH_SYMLINK | PATH_REP;
|
||||||
|
}
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
#ifdef __WITH_AF_UNIX
|
#ifdef __WITH_AF_UNIX
|
||||||
else if (rp->ReparseTag == IO_REPARSE_TAG_CYGUNIX)
|
else if (rp->ReparseTag == IO_REPARSE_TAG_CYGUNIX)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
What changed:
|
||||||
|
-------------
|
||||||
|
|
||||||
|
- Support WSL symlinks.
|
||||||
|
|
||||||
|
|
||||||
Bug Fixes:
|
Bug Fixes:
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,10 @@ be supported by upcoming mintty releases. For the reasoning, see
|
||||||
https://gitlab.freedesktop.org/terminal-wg/specifications/issues/9.
|
https://gitlab.freedesktop.org/terminal-wg/specifications/issues/9.
|
||||||
</para></listitem>
|
</para></listitem>
|
||||||
|
|
||||||
|
<listitem><para>
|
||||||
|
Support WSL symlinks.
|
||||||
|
</para></listitem>
|
||||||
|
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
Loading…
Reference in New Issue