public inbox for cygwin-cvs@sourceware.org
help / color / mirror / Atom feed
* [newlib-cygwin] Cygwin: symlinks: support WSL symlinks
@ 2020-03-27 11:12 Corinna Vinschen
0 siblings, 0 replies; only message in thread
From: Corinna Vinschen @ 2020-03-27 11:12 UTC (permalink / raw)
To: cygwin-cvs
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=4a36897af392c3bc0805f4802246b5d098ed19b7
commit 4a36897af392c3bc0805f4802246b5d098ed19b7
Author: Corinna Vinschen <corinna@vinschen.de>
Date: Fri Mar 27 12:12:31 2020 +0100
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>
Diff:
---
winsup/cygwin/path.cc | 73 +++++++++++++++++++++++++++++++++++++++++++++
winsup/cygwin/release/3.1.5 | 6 ++++
winsup/doc/new-features.xml | 4 +++
3 files changed, 83 insertions(+)
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index bda3ca1b5..7fa2bc5b5 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -2360,6 +2360,29 @@ check_reparse_point_string (PUNICODE_STRING subst)
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:
<0: Negative errno.
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))
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
else if (rp->ReparseTag == IO_REPARSE_TAG_CYGUNIX)
{
diff --git a/winsup/cygwin/release/3.1.5 b/winsup/cygwin/release/3.1.5
index e567ecb32..6f16aad93 100644
--- a/winsup/cygwin/release/3.1.5
+++ b/winsup/cygwin/release/3.1.5
@@ -1,3 +1,9 @@
+What changed:
+-------------
+
+- Support WSL symlinks.
+
+
Bug Fixes:
----------
diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml
index 9086302d3..a200300f2 100644
--- a/winsup/doc/new-features.xml
+++ b/winsup/doc/new-features.xml
@@ -82,6 +82,10 @@ be supported by upcoming mintty releases. For the reasoning, see
https://gitlab.freedesktop.org/terminal-wg/specifications/issues/9.
</para></listitem>
+<listitem><para>
+Support WSL symlinks.
+</para></listitem>
+
</itemizedlist>
</sect2>
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2020-03-27 11:12 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-27 11:12 [newlib-cygwin] Cygwin: symlinks: support WSL symlinks Corinna Vinschen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).