aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2025-02-27 13:51:39 +0100
committerCorinna Vinschen <corinna@vinschen.de>2025-02-27 13:51:39 +0100
commitd4a5c2be8bc09823b9afd4c6eafd41981e5ed645 (patch)
treed5a436c27c29937ccc6247c8c4c4bbdf935333c8
parentdc094c76657c2632196d3d67476a6c783ed0c285 (diff)
downloadnewlib-d4a5c2be8bc09823b9afd4c6eafd41981e5ed645.zip
newlib-d4a5c2be8bc09823b9afd4c6eafd41981e5ed645.tar.gz
newlib-d4a5c2be8bc09823b9afd4c6eafd41981e5ed645.tar.bz2
Cygwin: fhandler_netdrive: fix character conversion required for NFS shares
While filenames on NFS shares are converted internally to a widechar representation of the input bytes treated as the default system ANSI codepage (CP_ACP), this doesn't hold for share names. The names returned by WNetEnumResourceW are just the original bytes dropped verbatim into WCHAR. The original conversion from 7db1c6fc4e2a ("Cygwin: //server: revert to using WNet and support NFS shares") was erroneous in that it treated the bytes as ISO-8859-1, not as CP_ACP codepoints. Fix the conversion to convert from CP_ACP to widechar. Use a tmp_pathbuf buffer for the new widechar string instead of malloc/free. Extend the comment, better explaining the encoding difference between files and shares. Fixes: 7db1c6fc4e2a ("Cygwin: //server: revert to using WNet and support NFS shares") Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
-rw-r--r--winsup/cygwin/fhandler/netdrive.cc29
1 files changed, 17 insertions, 12 deletions
diff --git a/winsup/cygwin/fhandler/netdrive.cc b/winsup/cygwin/fhandler/netdrive.cc
index 58447ed..426542f 100644
--- a/winsup/cygwin/fhandler/netdrive.cc
+++ b/winsup/cygwin/fhandler/netdrive.cc
@@ -317,6 +317,7 @@ thread_netdrive_wnet (void *arg)
size_t entry_cache_size = DIR_cache.count ();
WCHAR provider[256], *dummy = NULL;
wchar_t srv_name[CYG_MAX_PATH];
+ wchar_t *nfs_namebuf = NULL;
NETRESOURCEW nri = { 0 };
LPNETRESOURCEW nro;
NETINFOSTRUCT netinfo;
@@ -397,6 +398,10 @@ thread_netdrive_wnet (void *arg)
ndi->err = ENOENT;
goto out;
}
+ /* We need a temporary buffer for the multibyte to widechar conversion
+ only required for NFS shares. */
+ if (!nfs_namebuf)
+ nfs_namebuf = tp.w_get ();
break;
case WNNC_NET_DAV:
/* WebDAV enumeration isn't supported, by the provider, but we can
@@ -447,19 +452,21 @@ thread_netdrive_wnet (void *arg)
if (net_type == WNNC_NET_MS_NFS)
{
- wchar_t *nm = name;
- /* Convert from "ANSI embedded in widechar" to multibyte and convert
- back to widechar. */
+ /* With MS NFS, the bytes of the share name on the remote side
+ are simply dropped into a WCHAR buffer without conversion to
+ Unicode. So convert from "multibyte embedded in widechar" to
+ real multibyte and then convert back to widechar here.
+
+ Quirky: This conversion is already performed for files on an
+ MS NFS filesystem when calling NtQueryDirectoryFile, but it's
+ not performed on the strings returned by WNetEnumResourceW. */
char mbname[wcslen (name) + 1];
char *mb = mbname;
- while ((*mb++ = *nm++))
+ while ((*mb++ = *name++))
;
- sys_mbstowcs_alloc (&name, HEAP_NOTHEAP, mbname);
- if (!name)
- {
- ndi->err = ENOMEM;
- goto out;
- }
+
+ name = nfs_namebuf;
+ MultiByteToWideChar (CP_ACP, 0, mbname, -1, name, NT_MAX_PATH);
}
/* Some providers have deep links so convert embedded '\\' to '/' here */
for (wchar_t *bs = name; (bs = wcschr (bs, L'\\')); *bs++ = L'/')
@@ -470,8 +477,6 @@ thread_netdrive_wnet (void *arg)
break;
if (cache_idx >= entry_cache_size)
DIR_cache.add (name);
- if (net_type == WNNC_NET_MS_NFS)
- free (name);
}
out:
if (dom)