Bruno Haible <br...@clisp.org> writes:

> The code looks good. Just please add comments
>   /* Documentation:
>      <https://learn.microsoft.com/...>  */
> before each use of a native Windows API. I would like that reviewing
> this code be easy. It's unlike the POSIX API, for which such annotations
> are not needed because we have it in memory or in our bookmarks.

Yes, I will probably forget them by the next time I look at it.

> Once you have added these, I can test it a bit on native Windows
> (not Wine).

Sure. For the most part the "test" just prints information. But I made
it fail if no mount points are returned (NULL). Hopefully that will
catch any systems that haven't been covered yet.

I pushed both attached patches.

Collin

>From 5f693944c4a5d9ad8334c27752a0a286d3fcb273 Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Tue, 18 Mar 2025 19:23:00 -0700
Subject: [PATCH 1/2] mountlist: Add support for native Windows.

* lib/mountlist.c (read_file_system_list) [_WIN32 && !__CYGWIN__]:
Enumerate all drive prefixes.
* m4/mountlist.m4 (gl_MOUNTLIST): Don't abort on native Windows.
---
 ChangeLog       |  5 +++++
 lib/mountlist.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++
 m4/mountlist.m4 |  6 +++++
 3 files changed, 70 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 93ea8a097f..29400e42b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,10 @@
 2025-03-18  Collin Funk  <collin.fu...@gmail.com>
 
+	mountlist: Add support for native Windows.
+	* lib/mountlist.c (read_file_system_list) [_WIN32 && !__CYGWIN__]:
+	Enumerate all drive prefixes.
+	* m4/mountlist.m4 (gl_MOUNTLIST): Don't abort on native Windows.
+
 	Prefer the __gnu_hurd__ macro over __GNU__.
 	* lib/get_ppid_of.c: Replace use of __GNU__ with __gnu_hurd__.
 	* lib/get_progname_of.c: Likewise.
diff --git a/lib/mountlist.c b/lib/mountlist.c
index 3376b730fc..7eacbf91b7 100644
--- a/lib/mountlist.c
+++ b/lib/mountlist.c
@@ -132,6 +132,10 @@
 # endif
 #endif
 
+#if defined _WIN32 && !defined __CYGWIN__
+# include <windows.h>
+#endif
+
 #ifndef HAVE_HASMNTOPT
 # define hasmntopt(mnt, opt) ((char *) 0)
 #endif
@@ -1092,6 +1096,61 @@ read_file_system_list (bool need_fs_type)
   }
 #endif /* MOUNTED_INTERIX_STATVFS */
 
+#if defined _WIN32 && !defined __CYGWIN__
+/* Don't assume that UNICODE is not defined.  */
+# undef GetDriveType
+# define GetDriveType GetDriveTypeA
+# undef GetVolumeInformation
+# define GetVolumeInformation GetVolumeInformationA
+  {
+    /* Windows has drive prefixes which are similar to mount points.
+       GetLogicalDrives returns a bitmask where the i-th bit is set
+       if ASCII 'A' + i is an available drive.  See:
+       <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getlogicaldrives>.  */
+    DWORD value = GetLogicalDrives ();
+    unsigned int i;
+
+    for (i = 0; i < 26; ++i)
+      {
+        if (value & (1U << i))
+          {
+            char fs_name[MAX_PATH + 1];
+            me = xmalloc (sizeof *me);
+            me->me_mountdir = xmalloc (4);
+            me->me_mountdir[0] = 'A' + i;
+            me->me_mountdir[1] = ':';
+            me->me_mountdir[2] = '\\';
+            me->me_mountdir[3] = '\0';
+            /* Check if drive is remote.  See:
+               <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getdrivetypea>.  */
+            me->me_remote = GetDriveType (me->me_mountdir) == DRIVE_REMOTE;
+            me->me_devname = NULL;
+            me->me_mntroot = NULL;
+            me->me_dev = (dev_t) -1;
+            me->me_dummy = 0;
+            /* Get the name of the file system.  See:
+               <https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-getvolumeinformationa>.  */
+            if (GetVolumeInformation (me->me_mountdir, NULL, 0, NULL, NULL,
+                                      NULL, fs_name, sizeof fs_name))
+              {
+                me->me_type = xstrdup (fs_name);
+                me->me_type_malloced = 1;
+              }
+            else
+              {
+                me->me_type = NULL;
+                me->me_type_malloced = 0;
+              }
+
+            /* Add to the linked list. */
+            *mtail = me;
+            mtail = &me->me_next;
+          }
+      }
+  }
+
+#endif
+
   *mtail = NULL;
   return mount_list;
 
diff --git a/m4/mountlist.m4 b/m4/mountlist.m4
index f86da32b9b..0b8e3f1da2 100644
--- a/m4/mountlist.m4
+++ b/m4/mountlist.m4
@@ -318,6 +318,12 @@ AC_DEFUN([gl_MOUNTLIST]
     esac
   fi
 
+  if test -z "$ac_list_mounted_fs"; then
+    case "$host_os" in
+      mingw* | windows*) ac_list_mounted_fs=found ;;
+    esac
+  fi
+
   if test -z "$ac_list_mounted_fs"; then
     AC_MSG_ERROR([could not determine how to read list of mounted file systems])
     # FIXME -- no need to abort building the whole package
-- 
2.48.1

>From f6c3f86ba93bfbb7c1079e38b3580495e4ed128b Mon Sep 17 00:00:00 2001
From: Collin Funk <collin.fu...@gmail.com>
Date: Tue, 18 Mar 2025 19:58:25 -0700
Subject: [PATCH 2/2] mountlist: Add tests.

* modules/mountlist-tests: New file.
* tests/test-mountlist.c: New file.
* modules/mountlist (Usable-in-testdir): Remove section.
* gnulib-tool.sh (func_create_testdir): Allow mountlist to be used in
testdirs.
---
 ChangeLog               |  7 ++++++
 gnulib-tool.sh          |  3 +--
 modules/mountlist       |  4 ----
 modules/mountlist-tests | 11 +++++++++
 tests/test-mountlist.c  | 53 +++++++++++++++++++++++++++++++++++++++++
 5 files changed, 72 insertions(+), 6 deletions(-)
 create mode 100644 modules/mountlist-tests
 create mode 100644 tests/test-mountlist.c

diff --git a/ChangeLog b/ChangeLog
index 29400e42b6..a0a8763da1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2025-03-18  Collin Funk  <collin.fu...@gmail.com>
 
+	mountlist: Add tests.
+	* modules/mountlist-tests: New file.
+	* tests/test-mountlist.c: New file.
+	* modules/mountlist (Usable-in-testdir): Remove section.
+	* gnulib-tool.sh (func_create_testdir): Allow mountlist to be used in
+	testdirs.
+
 	mountlist: Add support for native Windows.
 	* lib/mountlist.c (read_file_system_list) [_WIN32 && !__CYGWIN__]:
 	Enumerate all drive prefixes.
diff --git a/gnulib-tool.sh b/gnulib-tool.sh
index 0fbd805ebe..e377f9ea78 100755
--- a/gnulib-tool.sh
+++ b/gnulib-tool.sh
@@ -6559,10 +6559,9 @@ func_create_testdir ()
     # Except non-recursive-gnulib-prefix-hack, which represents a nonstandard
     # way of using Automake.
     # Except timevar, which lacks the required file timevar.def.
-    # Except mountlist, which aborts the configuration on mingw. FIXME.
     # Except lib-ignore, which leads to link errors when Sun C++ is used. FIXME.
     modules=`func_all_modules`
-    modules=`for m in $modules; do case $m in config-h | non-recursive-gnulib-prefix-hack | timevar | mountlist | lib-ignore) ;; *) echo $m;; esac; done`
+    modules=`for m in $modules; do case $m in config-h | non-recursive-gnulib-prefix-hack | timevar | lib-ignore) ;; *) echo $m;; esac; done`
   else
     # Validate the list of specified modules.
     modules=`for module in $modules; do func_verify_module; if test -n "$module"; then echo "$module"; fi; done`
diff --git a/modules/mountlist b/modules/mountlist
index ad039d1910..016ff2dd6f 100644
--- a/modules/mountlist
+++ b/modules/mountlist
@@ -1,10 +1,6 @@
 Description:
 Return list of mounted file systems.
 
-Usable-in-testdir:
-# This module aborts the configuration on mingw. FIXME
-no
-
 Files:
 lib/mountlist.h
 lib/mountlist.c
diff --git a/modules/mountlist-tests b/modules/mountlist-tests
new file mode 100644
index 0000000000..d44f23ef9c
--- /dev/null
+++ b/modules/mountlist-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-mountlist.c
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-mountlist
+check_PROGRAMS += test-mountlist
diff --git a/tests/test-mountlist.c b/tests/test-mountlist.c
new file mode 100644
index 0000000000..cf7d5dd03d
--- /dev/null
+++ b/tests/test-mountlist.c
@@ -0,0 +1,53 @@
+/* Test the mountlist module.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Collin Funk <collin.fu...@gmail.com>, 2025.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "mountlist.h"
+
+#include <stdio.h>
+
+#include "macros.h"
+
+int
+main (void)
+{
+  struct mount_entry *mounts;
+  struct mount_entry *p;
+
+  mounts = read_file_system_list (false);
+
+  /* Assume at least one mount point.  */
+  ASSERT (mounts != NULL);
+
+  for (p = mounts; p != NULL;)
+    {
+      struct mount_entry *next = p->me_next;
+      printf ("%s %s %s %s %s\n",
+              p->me_devname ? p->me_devname : "???",
+              p->me_mountdir ? p->me_mountdir : "???",
+              p->me_mntroot ? p->me_mntroot : "???",
+              p->me_type ? p->me_type : "???",
+              p->me_remote ? "remote" : "local");
+      free_mount_entry (p);
+      p = next;
+    }
+
+  return test_exit_status;
+}
-- 
2.48.1

Reply via email to