Hello,

Attached 2 patches:

  mountlist tests: add mountlist-tests module
  mountlist: add support for windows DOS-style drives

The second patch enables the completion of coreutils' "./configure"
under windows with mingw compiler (not the entire build, just
"configure") instead of failing with:

   configure: error: could not determine how to read list of mounted
                     file systems

This is a first step towards getting stock coreutils to compile
on mingw (and perhaps also findutils which uses mountlist).

Comments welcomed,
 - assaf
>From d1c3e9a61e7c1e9a6bab2b5198d24391e309adc0 Mon Sep 17 00:00:00 2001
From: Assaf Gordon <assafgor...@gmail.com>
Date: Wed, 10 Oct 2018 14:08:42 -0600
Subject: [PATCH 1/2] mountlist tests: add mountlist-tests module

Call read_file_system_list, print the list, and free the entries.
Typical output example:

  $ ./gnulib-tool -create-testdir -dir mnt-list mountlist-tests
  $ cd mnt-list
  $ ./configure && make
  $ ./gltests/test-mountlist
  devname:  proc
  mountdir: /proc
  mntdoor:  /
  type:     proc
  dev:      4
  dummy:    1
  remote:   0
  type_alc: 1

  devname:  /dev/sda1
  mountdir: /
  mntdoor:  /
  type:     ext4
  dev:      2049
  dummy:    0
  remote:   0
  type_alc: 1

  [...]

* modules/mountlist-tests: New module file.
* tests/test-mountlist.c: New test file.
---
 ChangeLog               | 29 +++++++++++++++++++++++++++++
 modules/mountlist-tests | 11 +++++++++++
 tests/test-mountlist.c  | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 88 insertions(+)
 create mode 100644 modules/mountlist-tests
 create mode 100644 tests/test-mountlist.c

diff --git a/ChangeLog b/ChangeLog
index 6161c05b6..aa490686f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2018-10-10  Assaf Gordon <assafgor...@gmail.com>
+
+	mountlist tests: add mountlist-tests module
+	Call read_file_system_list, print the list, and free the entries.
+	Typical output example:
+	  $ ./gnulib-tool -create-testdir -dir mnt-list mountlist-tests
+	  $ cd mnt-list
+	  $ ./configure && make
+	  $ ./gltests/test-mountlist
+	  devname:  proc
+	  mountdir: /proc
+	  mntdoor:  /
+	  type:     proc
+	  dev:      4
+	  dummy:    1
+	  remote:   0
+	  type_alc: 1
+	  devname:  /dev/sda1
+	  mountdir: /
+	  mntdoor:  /
+	  type:     ext4
+	  dev:      2049
+	  dummy:    0
+	  remote:   0
+	  type_alc: 1
+	  [...]
+	* modules/mountlist-tests: New module file.
+	* tests/test-mountlist.c: New test file.
+
 2018-10-08  Paul Eggert  <egg...@cs.ucla.edu>
 
 	fts: cleanup after FTS_NOATIME removal
diff --git a/modules/mountlist-tests b/modules/mountlist-tests
new file mode 100644
index 000000000..5fb380f90
--- /dev/null
+++ b/modules/mountlist-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-mountlist.c
+
+Depends-on:
+mountlist
+
+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 000000000..474afd3f3
--- /dev/null
+++ b/tests/test-mountlist.c
@@ -0,0 +1,48 @@
+/* Test of <mountlist.h> functions.
+   Copyright (C) 2018 Free Software Foundation, Inc.
+
+   This program 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 program 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 Assaf Gordon <assafgor...@gmail.com>, 2018 */
+
+#include <config.h>
+#include <stdio.h>
+#include <mountlist.h>
+
+int
+main ()
+{
+  struct mount_entry *mnt_ent = read_file_system_list (true);
+
+   while (mnt_ent)
+     {
+       struct mount_entry *mnt_free;
+
+       printf ("devname:  %s\n", mnt_ent->me_devname);
+       printf ("mountdir: %s\n", mnt_ent->me_mountdir);
+       printf ("mntdoor:  %s\n", mnt_ent->me_mntroot);
+       printf ("type:     %s\n", mnt_ent->me_type);
+       printf ("dev:      %ld\n", (long int)mnt_ent->me_dev);
+       printf ("dummy:    %d\n", mnt_ent->me_dummy);
+       printf ("remote:   %d\n", mnt_ent->me_remote);
+       printf ("type_alc: %d\n", mnt_ent->me_type_malloced);
+       putchar ('\n');
+
+       mnt_free = mnt_ent;
+       mnt_ent = mnt_ent->me_next;
+       free_mount_entry (mnt_free);
+     }
+
+  return 0;
+}
-- 
2.11.0

>From 4de125a449fd90b865bdf69a0632939531a71fd6 Mon Sep 17 00:00:00 2001
From: Assaf Gordon <assafgor...@gmail.com>
Date: Wed, 10 Oct 2018 14:13:10 -0600
Subject: [PATCH 2/2] mountlist: add support for windows DOS-style drives

Support basic DOS-style drives on Windows (e.g. C:\, D:\, Q:\).
Using Win32 API that should be backwards compatible back to Windows XP.

Example of 'struct mount_entry' (as printed by 'test-mountlist'):

  devname:  \Device\HarddiskVolume2
  mountdir: C:\
  mntdoor:  C:\
  type:     NTFS
  dev:      -1
  dummy:    0
  remote:   0
  type_alc: 1

  devname:  \Device\HarddiskVolume4
  mountdir: D:\
  mntdoor:  D:\
  type:     NTFS
  dev:      -1
  dummy:    0
  remote:   0
  type_alc: 1

* m4/ls-mntd-fs.m4: Check for <windows.h> and GetLogicalDrives()
function. If found, assume Win32 mount list method.
Adds MOUNTED_GETLOGICALDRIVES to config.h,
and fu_cv_getlogicaldrives={yes,no} to the ./configure script.
* lib/mountlist.c (re_remote): Include this function for both CYGWIN and
Win32.
(read_file_system_list): If using Win32, call GetLogicalDrives(),
GetVolumeInformation() and QueryDosDevice() to populate the mount
entries list.
---
 ChangeLog        | 33 ++++++++++++++++++++++++
 lib/mountlist.c  | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 m4/ls-mntd-fs.m4 | 20 +++++++++++++++
 3 files changed, 129 insertions(+), 1 deletion(-)

diff --git a/ChangeLog b/ChangeLog
index aa490686f..3f6e7f207 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,38 @@
 2018-10-10  Assaf Gordon <assafgor...@gmail.com>
 
+	mountlist: add support for windows DOS-style drives
+	Support basic DOS-style drives on Windows (e.g. C:\, D:\, Q:\).
+	Using Win32 API that should be backwards compatible back to Windows XP.
+	Example of 'struct mount_entry' (as printed by 'test-mountlist'):
+	  devname:  \Device\HarddiskVolume2
+	  mountdir: C:\
+	  mntdoor:  C:\
+	  type:     NTFS
+	  dev:      -1
+	  dummy:    0
+	  remote:   0
+	  type_alc: 1
+	  devname:  \Device\HarddiskVolume4
+	  mountdir: D:\
+	  mntdoor:  D:\
+	  type:     NTFS
+	  dev:      -1
+	  dummy:    0
+	  remote:   0
+	  type_alc: 1
+	* m4/ls-mntd-fs.m4: Check for <windows.h> and GetLogicalDrives()
+	function. If found, assume Win32 mount list method.
+	Adds MOUNTED_GETLOGICALDRIVES to config.h,
+	and fu_cv_getlogicaldrives={yes,no} to the ./configure script.
+	* lib/mountlist.c (re_remote): Include this function for both CYGWIN and
+	Win32.
+	(read_file_system_list): If using Win32, call GetLogicalDrives(),
+	GetVolumeInformation() and QueryDosDevice() to populate the mount
+	entries list.
+
+
+2018-10-10  Assaf Gordon <assafgor...@gmail.com>
+
 	mountlist tests: add mountlist-tests module
 	Call read_file_system_list, print the list, and free the entries.
 	Typical output example:
diff --git a/lib/mountlist.c b/lib/mountlist.c
index b691f3808..12964d1ef 100644
--- a/lib/mountlist.c
+++ b/lib/mountlist.c
@@ -135,6 +135,10 @@
 # include <sys/mntent.h>
 #endif
 
+#ifdef  MOUNTED_GETLOGICALDRIVES /* Win32 API */
+#  include <windows.h>
+#endif
+
 #ifndef HAVE_HASMNTOPT
 # define hasmntopt(mnt, opt) ((char *) 0)
 #endif
@@ -196,7 +200,7 @@
   (ME_DUMMY_0 (Fs_name, Fs_type) || strcmp (Fs_type, "none") == 0)
 #endif
 
-#ifdef __CYGWIN__
+#if defined __CYGWIN__ || defined MOUNTED_GETLOGICALDRIVES
 # include <windows.h>
 # define ME_REMOTE me_remote
 /* All cygwin mount points include ':' or start with '//'; so it
@@ -1105,6 +1109,77 @@ read_file_system_list (bool need_fs_type)
   }
 #endif /* MOUNTED_INTERIX_STATVFS */
 
+#ifdef MOUNTED_GETLOGICALDRIVES
+  {
+    int i;
+    char RootPathName[4];
+    char VolumeName[MAX_PATH+1];
+    DWORD VolumeSerialNum;
+    DWORD MaxComponentLen;
+    DWORD FileSystemFlags;
+    char FileSystemName[MAX_PATH+1];
+    char DosDevicePath[MAX_PATH+1];
+    DWORD dw;
+    DWORD ld = GetLogicalDrives();
+
+    if (ld == 0)
+      return NULL;
+
+    for (i=0 ; i<32; ++i)
+      {
+
+        if (!(ld & (1<<i)))
+          continue;
+
+        snprintf (RootPathName, 4, "%c:\\", (char)('A'+i));
+        memset (VolumeName, 0, sizeof (VolumeName));
+        memset (FileSystemName, 0, sizeof (FileSystemName));
+        VolumeSerialNum = 0;
+        MaxComponentLen = 0;
+        FileSystemFlags = 0;
+
+        /* There are various valid reasons why this could fail.
+           GetLastError() can provide more information, e.g.:
+           ERROR_ACCESS_DENIED (0x5): permission denied
+           ERROR_NOT_READY (0x15): e.g. a CDROM drive without a CD inside.  */
+        if (!GetVolumeInformation (RootPathName,
+                                   VolumeName, sizeof (VolumeName),
+                                   &VolumeSerialNum,
+                                   &MaxComponentLen,
+                                   &FileSystemFlags,
+                                   FileSystemName, sizeof (FileSystemName)))
+          continue;
+
+        /* Chop the trailing backslash - QueryDosDevice does not accept it.  */
+        RootPathName[2] = '\x0';
+        dw = QueryDosDevice (RootPathName,
+                             DosDevicePath, sizeof (DosDevicePath));
+
+        /* FIXME: for now, the buffer is fixed size. If the call fails
+           or if the buffer is too small - skip the drive.  */
+        if (dw == 0 || dw == ERROR_INSUFFICIENT_BUFFER)
+          continue;
+
+        /* restore the backslash.  */
+        RootPathName[2] = '\\';
+
+        me = xmalloc (sizeof *me);
+        me->me_devname = xstrdup (DosDevicePath);
+        me->me_mountdir = xstrdup (RootPathName);
+        me->me_mntroot = xstrdup (RootPathName);
+        me->me_type = xstrdup (FileSystemName);
+        me->me_type_malloced = 1;
+        me->me_dummy = 0;
+        me->me_remote = me_remote (RootPathName, NULL);
+        me->me_dev = -1;
+
+        /* Add to the linked list. */
+        *mtail = me;
+        mtail = &me->me_next;
+      }
+  }
+#endif /* MOUNTED_GETLOGICALDRIVES */
+
   *mtail = NULL;
   return mount_list;
 
diff --git a/m4/ls-mntd-fs.m4 b/m4/ls-mntd-fs.m4
index 4a84f0aca..e3a4ae5ce 100644
--- a/m4/ls-mntd-fs.m4
+++ b/m4/ls-mntd-fs.m4
@@ -349,6 +349,26 @@ if test -z "$ac_list_mounted_fs"; then
 fi
 
 if test -z "$ac_list_mounted_fs"; then
+  # Win32 API (based on GetLogicalDrives() function)
+  AC_MSG_CHECKING([for Win32API Volume Information])
+  AC_CACHE_VAL([fu_cv_getlogicaldrives],
+                 [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
+#include <windows.h>
+]],
+                    [[ DWORD dw = GetLogicalDrives(); return 0; ]])],
+                    [fu_cv_getlogicaldrives=yes],
+                    [fu_cv_getlogicaldrives=no])])
+  AC_MSG_RESULT([$fu_cv_getlogicaldrives])
+  if test $fu_cv_getlogicaldrives = yes; then
+    ac_list_mounted_fs=found
+    AC_DEFINE([MOUNTED_GETLOGICALDRIVES], [1],
+      [Define if there is a function named GetLogicalDrives for reading the
+       list of logical drives.
+       (Win32 API)])
+  fi
+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
   # Can't build mountlist.c or anything that needs its functions
-- 
2.11.0

Reply via email to