diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2025-02-27 13:51:39 +0100 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2025-02-27 13:51:39 +0100 |
commit | d4a5c2be8bc09823b9afd4c6eafd41981e5ed645 (patch) | |
tree | d5a436c27c29937ccc6247c8c4c4bbdf935333c8 | |
parent | dc094c76657c2632196d3d67476a6c783ed0c285 (diff) | |
download | newlib-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.cc | 29 |
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) |