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