[PATCH v4 2/3] Cygwin: expose all windows volume mount points.
Jeremy Drake
cygwin@jdrake.com
Thu Feb 13 01:40:19 GMT 2025
They are exposed via the getmntent API and proc filesystem entries
dealing with mounts. This allows things like `df` to show volumes
that are only mounted on directories, not on drive letters.
Addresses: https://cygwin.com/pipermail/cygwin/2025-February/257251.html
Signed-off-by: Jeremy Drake <cygwin@jdrake.com>
---
winsup/cygwin/cygtls.cc | 6 ++
winsup/cygwin/fhandler/process.cc | 19 ++---
winsup/cygwin/local_includes/cygtls.h | 6 +-
winsup/cygwin/local_includes/mount.h | 5 +-
winsup/cygwin/mount.cc | 116 ++++++++++++++++++--------
5 files changed, 100 insertions(+), 52 deletions(-)
diff --git a/winsup/cygwin/cygtls.cc b/winsup/cygwin/cygtls.cc
index 1134adc3e2..13d133f47c 100644
--- a/winsup/cygwin/cygtls.cc
+++ b/winsup/cygwin/cygtls.cc
@@ -121,6 +121,12 @@ _cygtls::remove (DWORD wait)
CloseHandle (h);
}
+ if (locals.drivemappings)
+ {
+ delete locals.drivemappings;
+ locals.drivemappings = NULL;
+ }
+
/* Close handle and free memory used by select. */
if (locals.select.sockevt)
{
diff --git a/winsup/cygwin/fhandler/process.cc b/winsup/cygwin/fhandler/process.cc
index f779028116..550da2a820 100644
--- a/winsup/cygwin/fhandler/process.cc
+++ b/winsup/cygwin/fhandler/process.cc
@@ -1395,16 +1395,11 @@ format_process_mountstuff (void *data, char *&destbuf, bool mountinfo)
u_shared = user_shared;
mount_info *mtab = &u_shared->mountinfo;
- /* Store old value of _my_tls.locals here. */
- int iteration = _my_tls.locals.iteration;
- unsigned available_drives = _my_tls.locals.available_drives;
- /* This reinitializes the above values in _my_tls. */
- setmntent (NULL, NULL);
- /* Restore iteration immediately since it's not used below. We use the
- local iteration variable instead*/
- _my_tls.locals.iteration = iteration;
-
- for (iteration = 0; (mnt = mtab->getmntent (iteration)); ++iteration)
+ /* Store old value of _my_tls.locals.drivemappings here. */
+ class dos_drive_mappings *drivemappings = _my_tls.locals.drivemappings;
+ _my_tls.locals.drivemappings = NULL;
+
+ for (int iteration = 0; (mnt = mtab->getmntent (iteration)); ++iteration)
{
/* We have no access to the drives mapped into another user session and
_my_tls.locals.available_drives contains the mappings of the current
@@ -1470,8 +1465,8 @@ format_process_mountstuff (void *data, char *&destbuf, bool mountinfo)
}
}
- /* Restore available_drives */
- _my_tls.locals.available_drives = available_drives;
+ /* Restore old value of _my_tls.locals.drivemappings here. */
+ _my_tls.locals.drivemappings = drivemappings;
if (u_hdl) /* Only not-NULL if open_shared has been called. */
{
diff --git a/winsup/cygwin/local_includes/cygtls.h b/winsup/cygwin/local_includes/cygtls.h
index d814814b19..dfd3198435 100644
--- a/winsup/cygwin/local_includes/cygtls.h
+++ b/winsup/cygwin/local_includes/cygtls.h
@@ -93,10 +93,10 @@ struct _local_storage
int dl_error;
char dl_buffer[256];
- /* path.cc */
+ /* mount.cc */
struct mntent mntbuf;
int iteration;
- unsigned available_drives;
+ class dos_drive_mappings *drivemappings;
char mnt_type[80];
char mnt_opts[80];
char mnt_fsname[CYG_MAX_PATH];
@@ -181,7 +181,7 @@ public: /* Do NOT remove this public: line, it's a marker for gentls_offsets. */
siginfo_t *sigwait_info;
HANDLE signal_arrived;
bool will_wait_for_signal;
-#if 1
+#if 0
long __align; /* Needed to align context to 16 byte. */
#endif
/* context MUST be aligned to 16 byte, otherwise RtlCaptureContext fails.
diff --git a/winsup/cygwin/local_includes/mount.h b/winsup/cygwin/local_includes/mount.h
index c96b34781e..3049de8ba3 100644
--- a/winsup/cygwin/local_includes/mount.h
+++ b/winsup/cygwin/local_includes/mount.h
@@ -216,6 +216,7 @@ class mount_info
bool from_fstab (bool user, WCHAR [], PWCHAR);
int cygdrive_win32_path (const char *src, char *dst, int& unit);
+ struct mntent *cygdrive_getmntent ();
};
class dos_drive_mappings
@@ -231,11 +232,13 @@ class dos_drive_mappings
wchar_t *path;
size_t len;
} dos;
- } *mappings;
+ } *mappings, *cur_mapping;
+ mapping::dosmount *cur_dos;
public:
dos_drive_mappings ();
~dos_drive_mappings ();
wchar_t *fixup_if_match (wchar_t *path);
+ const wchar_t *next_dos_mount ();
};
#endif
diff --git a/winsup/cygwin/mount.cc b/winsup/cygwin/mount.cc
index 4be24fbe84..722dc2aef5 100644
--- a/winsup/cygwin/mount.cc
+++ b/winsup/cygwin/mount.cc
@@ -1645,14 +1645,8 @@ fillout_mntent (const char *native_path, const char *posix_path, unsigned flags)
struct mntent& ret=_my_tls.locals.mntbuf;
bool append_bs = false;
- /* Remove drivenum from list if we see a x: style path */
if (strlen (native_path) == 2 && native_path[1] == ':')
- {
- int drivenum = cyg_tolower (native_path[0]) - 'a';
- if (drivenum >= 0 && drivenum <= 31)
- _my_tls.locals.available_drives &= ~(1 << drivenum);
append_bs = true;
- }
/* Pass back pointers to mount_table strings reserved for use by
getmntent rather than pointers to strings in the internal mount
@@ -1744,41 +1738,74 @@ mount_item::getmntent ()
return fillout_mntent (native_path, posix_path, flags);
}
-static struct mntent *
-cygdrive_getmntent ()
+struct mntent *
+mount_info::cygdrive_getmntent ()
{
- char native_path[4];
- char posix_path[CYG_MAX_PATH];
- DWORD mask = 1, drive = 'a';
- struct mntent *ret = NULL;
+ tmp_pathbuf tp;
+ const wchar_t *wide_path;
+ char *win32_path, *posix_path;
+ int err;
- while (_my_tls.locals.available_drives)
+ if (!_my_tls.locals.drivemappings)
+ _my_tls.locals.drivemappings = new dos_drive_mappings ();
+
+ wide_path = _my_tls.locals.drivemappings->next_dos_mount ();
+ if (wide_path)
{
- for (/* nothing */; drive <= 'z'; mask <<= 1, drive++)
- if (_my_tls.locals.available_drives & mask)
- break;
+ win32_path = tp.c_get ();
+ sys_wcstombs (win32_path, NT_MAX_PATH, wide_path);
+ posix_path = tp.c_get ();
+ if ((err = conv_to_posix_path (win32_path, posix_path, 0)))
+ {
+ set_errno (err);
+ return NULL;
+ }
- __small_sprintf (native_path, "%c:\\", cyg_toupper (drive));
- if (GetFileAttributes (native_path) == INVALID_FILE_ATTRIBUTES)
+ return fillout_mntent (win32_path, posix_path, cygdrive_flags);
+ }
+ else
+ {
+ if (_my_tls.locals.drivemappings)
{
- _my_tls.locals.available_drives &= ~mask;
- continue;
+ delete _my_tls.locals.drivemappings;
+ _my_tls.locals.drivemappings = NULL;
}
- native_path[2] = '\0';
- __small_sprintf (posix_path, "%s%c", mount_table->cygdrive, drive);
- ret = fillout_mntent (native_path, posix_path, mount_table->cygdrive_flags);
- break;
+ return NULL;
}
-
- return ret;
}
struct mntent *
mount_info::getmntent (int x)
{
if (x < 0 || x >= nmounts)
- return cygdrive_getmntent ();
-
+ {
+ struct mntent *ret;
+ /* de-duplicate against explicit mount entries */
+ while ((ret = cygdrive_getmntent ()))
+ {
+ tmp_pathbuf tp;
+ char *backslash_fsname = NULL;
+ for (int i = 0; i < nmounts; ++i)
+ {
+ if (!strcmp (ret->mnt_dir, mount[i].posix_path))
+ {
+ /* mount_item::native_path has backslashes, but
+ mntent::mnt_fsname has forward slashes. Lazily
+ backslashify only if mnt_dir equals posix_path. */
+ if (!backslash_fsname)
+ {
+ backslash_fsname = tp.c_get ();
+ backslashify (ret->mnt_fsname, backslash_fsname, false);
+ }
+ if (strcasematch (backslash_fsname, mount[i].native_path))
+ goto cygdrive_mntent_continue;
+ }
+ }
+ break;
+cygdrive_mntent_continue:;
+ }
+ return ret;
+ }
return mount[native_sorted[x]].getmntent ();
}
@@ -1943,14 +1970,11 @@ extern "C" FILE *
setmntent (const char *filep, const char *)
{
_my_tls.locals.iteration = 0;
- _my_tls.locals.available_drives = GetLogicalDrives ();
- /* Filter floppy drives on A: and B: */
- if ((_my_tls.locals.available_drives & 1)
- && get_disk_type (L"A:") == DT_FLOPPY)
- _my_tls.locals.available_drives &= ~1;
- if ((_my_tls.locals.available_drives & 2)
- && get_disk_type (L"B:") == DT_FLOPPY)
- _my_tls.locals.available_drives &= ~2;
+ if (_my_tls.locals.drivemappings)
+ {
+ delete _my_tls.locals.drivemappings;
+ _my_tls.locals.drivemappings = NULL;
+ }
return (FILE *) filep;
}
@@ -1996,6 +2020,8 @@ endmntent (FILE *)
dos_drive_mappings::dos_drive_mappings ()
: mappings(0)
+, cur_mapping(0)
+, cur_dos(0)
{
tmp_pathbuf tp;
wchar_t vol[64]; /* Long enough for Volume GUID string */
@@ -2112,6 +2138,24 @@ dos_drive_mappings::fixup_if_match (wchar_t *path)
return path;
}
+const wchar_t *
+dos_drive_mappings::next_dos_mount ()
+{
+ if (cur_dos)
+ cur_dos = cur_dos->next;
+ while (!cur_dos)
+ {
+ if (cur_mapping)
+ cur_mapping = cur_mapping->next;
+ else
+ cur_mapping = mappings;
+ if (!cur_mapping)
+ return NULL;
+ cur_dos = &cur_mapping->dos;
+ }
+ return cur_dos->path;
+}
+
dos_drive_mappings::~dos_drive_mappings ()
{
mapping *n = 0;
--
2.47.1.windows.2
More information about the Cygwin-patches
mailing list