4
0
mirror of git://sourceware.org/git/newlib-cygwin.git synced 2025-02-28 20:15:24 +08:00

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>
This commit is contained in:
Corinna Vinschen 2025-02-27 13:51:39 +01:00
parent dc094c7665
commit d4a5c2be8b

View File

@ -317,6 +317,7 @@ thread_netdrive_wnet (void *arg)
size_t entry_cache_size = DIR_cache.count (); size_t entry_cache_size = DIR_cache.count ();
WCHAR provider[256], *dummy = NULL; WCHAR provider[256], *dummy = NULL;
wchar_t srv_name[CYG_MAX_PATH]; wchar_t srv_name[CYG_MAX_PATH];
wchar_t *nfs_namebuf = NULL;
NETRESOURCEW nri = { 0 }; NETRESOURCEW nri = { 0 };
LPNETRESOURCEW nro; LPNETRESOURCEW nro;
NETINFOSTRUCT netinfo; NETINFOSTRUCT netinfo;
@ -397,6 +398,10 @@ thread_netdrive_wnet (void *arg)
ndi->err = ENOENT; ndi->err = ENOENT;
goto out; 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; break;
case WNNC_NET_DAV: case WNNC_NET_DAV:
/* WebDAV enumeration isn't supported, by the provider, but we can /* 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) if (net_type == WNNC_NET_MS_NFS)
{ {
wchar_t *nm = name; /* With MS NFS, the bytes of the share name on the remote side
/* Convert from "ANSI embedded in widechar" to multibyte and convert are simply dropped into a WCHAR buffer without conversion to
back to widechar. */ 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 mbname[wcslen (name) + 1];
char *mb = mbname; char *mb = mbname;
while ((*mb++ = *nm++)) while ((*mb++ = *name++))
; ;
sys_mbstowcs_alloc (&name, HEAP_NOTHEAP, mbname);
if (!name) name = nfs_namebuf;
{ MultiByteToWideChar (CP_ACP, 0, mbname, -1, name, NT_MAX_PATH);
ndi->err = ENOMEM;
goto out;
}
} }
/* Some providers have deep links so convert embedded '\\' to '/' here */ /* Some providers have deep links so convert embedded '\\' to '/' here */
for (wchar_t *bs = name; (bs = wcschr (bs, L'\\')); *bs++ = L'/') for (wchar_t *bs = name; (bs = wcschr (bs, L'\\')); *bs++ = L'/')
@ -470,8 +477,6 @@ thread_netdrive_wnet (void *arg)
break; break;
if (cache_idx >= entry_cache_size) if (cache_idx >= entry_cache_size)
DIR_cache.add (name); DIR_cache.add (name);
if (net_type == WNNC_NET_MS_NFS)
free (name);
} }
out: out:
if (dom) if (dom)