[PATCH] Cygwin: include network mounts in cygdrive_getmntent.
Lionel Cons
lionelcons1972@gmail.com
Wed Feb 19 00:11:21 GMT 2025
Does this patch cover global mounts, i.e. SMB mounted by user
LocalSystem on a driver letter are visible to ALL users. Local users
logons can override the same drive letter via per-user net use
Example:
LocalSystem mounts H: to \\homeserver\disk4\users, this is visible to
all users in a system
User "lionel" mounts H: to \\lionelsserver\data\homedir, this is
visible to the current Logon session
Lionel
On Tue, 18 Feb 2025 at 22:25, Jeremy Drake via Cygwin-patches
<cygwin-patches@cygwin.com> wrote:
>
> After migrating from GetLogicalDrives to Find(First|Next)VolumeW, mapped
> network drives no longer showed up in getmntent output. To fix that,
> also iterate GetLogicalDriveStringsW when builing dos_drive_mappings,
> and merge with volume mounts (skipping any volume mounts that are just
> mounted on the root of a drive, and replacing the dos mounts in the
> mapping for a volume which is mounted on both a drive root and a
> directory).
>
> Fixes: 04a5b072940cc ("Cygwin: expose all windows volume mount points.")
> Addresses: https://cygwin.com/pipermail/cygwin/2025-February/257384.html
> Signed-off-by: Jeremy Drake <cygwin@jdrake.com>
> ---
>
> This was generated on top of the patch
> https://cygwin.com/pipermail/cygwin-patches/2025q1/013390.html but should
> be able to be applied without it.
>
> winsup/cygwin/mount.cc | 145 ++++++++++++++++++++++++++++++++---------
> 1 file changed, 113 insertions(+), 32 deletions(-)
>
> diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
> index a3d9e5bd0f..68414f13af 100644
> --- a/winsup/cygwin/mount.cc
> +++ b/winsup/cygwin/mount.cc
> @@ -1995,6 +1995,40 @@ endmntent (FILE *)
> return 1;
> }
>
> +static bool
> +resolve_dos_device (const wchar_t *dosname, wchar_t *devpath)
> +{
> + if (QueryDosDeviceW (dosname, devpath, NT_MAX_PATH))
> + {
> + /* The DOS drive mapping can be another symbolic link. If so,
> + the mapping won't work since the section name is the name
> + after resolving all symlinks. Resolve symlinks here, too. */
> + for (int syml_cnt = 0; syml_cnt < SYMLOOP_MAX; ++syml_cnt)
> + {
> + UNICODE_STRING upath;
> + OBJECT_ATTRIBUTES attr;
> + NTSTATUS status;
> + HANDLE h;
> +
> + RtlInitUnicodeString (&upath, devpath);
> + InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE,
> + NULL, NULL);
> + status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY, &attr);
> + if (!NT_SUCCESS (status))
> + break;
> + RtlInitEmptyUnicodeString (&upath, devpath, (NT_MAX_PATH - 1)
> + * sizeof (WCHAR));
> + status = NtQuerySymbolicLinkObject (h, &upath, NULL);
> + NtClose (h);
> + if (!NT_SUCCESS (status))
> + break;
> + devpath[upath.Length / sizeof (WCHAR)] = L'\0';
> + }
> + return true;
> + }
> + return false;
> +}
> +
> dos_drive_mappings::dos_drive_mappings ()
> : mappings(0)
> , cur_mapping(0)
> @@ -2004,6 +2038,44 @@ dos_drive_mappings::dos_drive_mappings ()
> wchar_t vol[64]; /* Long enough for Volume GUID string */
> wchar_t *devpath = tp.w_get ();
> wchar_t *mounts = tp.w_get ();
> + mapping **nextm = &mappings;
> + mapping *endfirstloop = NULL;
> + DWORD len;
> +
> + /* Iterate over all drive letters, fetch the DOS device path */
> + if (!(len = GetLogicalDriveStringsW (NT_MAX_PATH - 1, mounts)) ||
> + len >= NT_MAX_PATH)
> + debug_printf ("GetLogicalDriveStringsW, %E");
> + else {
> + for (wchar_t *mount = mounts; *mount; mount += len + 2)
> + {
> + len = wcslen (mount);
> + mount[--len] = L'\0'; /* Drop trailing backslash */
> + if (resolve_dos_device (mount, devpath))
> + {
> + mapping *m = new mapping ();
> + if (m)
> + {
> + m->dos.path = wcsdup (mount);
> + m->ntdevpath = wcsdup (devpath);
> + if (!m->dos.path || !m->ntdevpath)
> + {
> + free (m->dos.path);
> + free (m->ntdevpath);
> + delete m;
> + continue;
> + }
> + m->dos.len = len;
> + m->ntlen = wcslen (m->ntdevpath);
> + *nextm = endfirstloop = m;
> + nextm = &m->next;
> + }
> + }
> + else
> + debug_printf ("Unable to determine the native mapping for %ls "
> + "(error %E)", mount);
> + }
> + }
>
> /* Iterate over all volumes, fetch the list of DOS paths the volume is
> mounted to. */
> @@ -2011,43 +2083,22 @@ dos_drive_mappings::dos_drive_mappings ()
> if (sh == INVALID_HANDLE_VALUE)
> debug_printf ("FindFirstVolumeW, %E");
> else {
> - mapping **nextm = &mappings;
> do
> {
> - /* Skip drives which are not mounted. */
> - DWORD len;
> + /* Skip volumes which are not mounted. */
> if (!GetVolumePathNamesForVolumeNameW (vol, mounts, NT_MAX_PATH, &len)
> || mounts[0] == L'\0')
> continue;
> + /* Skip volumes which are only mounted to the root of a drive letter:
> + they were handled in the loop above */
> + if (len == 5 && mounts[1] == L':' && mounts[2] == L'\\' && !mounts[3])
> + continue;
> +
> *wcsrchr (vol, L'\\') = L'\0';
> - if (QueryDosDeviceW (vol + 4, devpath, NT_MAX_PATH))
> + if (resolve_dos_device (vol + 4, devpath))
> {
> - /* The DOS drive mapping can be another symbolic link. If so,
> - the mapping won't work since the section name is the name
> - after resolving all symlinks. Resolve symlinks here, too. */
> - for (int syml_cnt = 0; syml_cnt < SYMLOOP_MAX; ++syml_cnt)
> - {
> - UNICODE_STRING upath;
> - OBJECT_ATTRIBUTES attr;
> - NTSTATUS status;
> - HANDLE h;
> -
> - RtlInitUnicodeString (&upath, devpath);
> - InitializeObjectAttributes (&attr, &upath,
> - OBJ_CASE_INSENSITIVE, NULL, NULL);
> - status = NtOpenSymbolicLinkObject (&h, SYMBOLIC_LINK_QUERY,
> - &attr);
> - if (!NT_SUCCESS (status))
> - break;
> - RtlInitEmptyUnicodeString (&upath, devpath, (NT_MAX_PATH - 1)
> - * sizeof (WCHAR));
> - status = NtQuerySymbolicLinkObject (h, &upath, NULL);
> - NtClose (h);
> - if (!NT_SUCCESS (status))
> - break;
> - devpath[upath.Length / sizeof (WCHAR)] = L'\0';
> - }
> mapping *m = new mapping ();
> + bool hadrootmount = false;
> if (m)
> {
> /* store mount point list */
> @@ -2072,15 +2123,45 @@ dos_drive_mappings::dos_drive_mappings ()
> dos->path = mount;
> dos->len = wcslen (dos->path);
> dos->path[--dos->len] = L'\0'; /* Drop trailing backslash */
> + if (dos->len == 2 && dos->path[1] == L':')
> + hadrootmount = true;
> }
> m->ntlen = wcslen (m->ntdevpath);
> - *nextm = m;
> - nextm = &m->next;
> + if (hadrootmount)
> + {
> + /* This device has already been added to the mappings list
> + in the first loop above, but with only the drive root
> + mount. Find that entry and replace it with the complete
> + list of mounts. */
> + hadrootmount = false;
> + for (mapping *m2 = mappings;
> + endfirstloop && m2 != endfirstloop->next;
> + m2 = m2->next)
> + {
> + if (m->ntlen == m2->ntlen &&
> + !wcscmp (m->ntdevpath, m2->ntdevpath))
> + {
> + free (m2->dos.path);
> + m2->dos.next = m->dos.next;
> + m2->dos.path = m->dos.path;
> + m2->dos.len = m->dos.len;
> + free (m->ntdevpath);
> + delete m;
> + hadrootmount = true;
> + break;
> + }
> + }
> + }
> + if (!hadrootmount)
> + {
> + *nextm = m;
> + nextm = &m->next;
> + }
> }
> }
> else
> debug_printf ("Unable to determine the native mapping for %ls "
> - "(error %u)", vol, GetLastError ());
> + "(error %E)", vol);
> }
> while (FindNextVolumeW (sh, vol, 64));
> FindVolumeClose (sh);
> --
> 2.48.1.windows.1
>
--
Lionel
More information about the Cygwin-patches
mailing list