[Libguestfs] [PATCH v7 19/29] daemon: Reimplement ‘list_filesystems’ API in the daemon, in OCaml.

Richard W.M. Jones rjones at redhat.com
Mon Jun 19 15:39:44 UTC 2017


Move the list_filesystems API into the daemon, reimplementing it in
OCaml.  Since this API makes many other API calls, it runs a lot
faster in the daemon.
---
 daemon/Makefile.am        |   2 +
 daemon/ldm.ml             |   3 +
 daemon/ldm.mli            |   2 +
 daemon/listfs.ml          | 156 +++++++++++++++++++++++++++++
 daemon/listfs.mli         |  19 ++++
 daemon/lvm.ml             |   3 +
 daemon/lvm.mli            |   2 +
 docs/C_SOURCE_FILES       |   1 -
 generator/actions_core.ml |  75 +++++++-------
 generator/daemon.ml       |  59 ++++++++++-
 generator/proc_nr.ml      |   1 +
 lib/MAX_PROC_NR           |   2 +-
 lib/Makefile.am           |   1 -
 lib/listfs.c              | 246 ----------------------------------------------
 14 files changed, 285 insertions(+), 287 deletions(-)

diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 459b5d7cc..fbe4734cf 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -265,6 +265,7 @@ SOURCES_MLI = \
 	is.mli \
 	ldm.mli \
 	link.mli \
+	listfs.mli \
 	lvm.mli \
 	md.mli \
 	mount.mli \
@@ -292,6 +293,7 @@ SOURCES_ML = \
 	md.ml \
 	mount.ml \
 	parted.ml \
+	listfs.ml \
 	realpath.ml \
 	callbacks.ml \
 	daemon.ml
diff --git a/daemon/ldm.ml b/daemon/ldm.ml
index dc7b36f9c..19cd03e83 100644
--- a/daemon/ldm.ml
+++ b/daemon/ldm.ml
@@ -20,6 +20,9 @@ open Std_utils
 
 open Utils
 
+external available : unit -> bool =
+  "guestfs_int_daemon_optgroup_lvm2_available" "noalloc"
+
 (* All device mapper devices are called /dev/mapper/ldm_vol_*.  XXX We
  * could tighten this up in future if ldmtool had a way to read these
  * names back after they have been created.
diff --git a/daemon/ldm.mli b/daemon/ldm.mli
index 789abb0b3..e6edfabd8 100644
--- a/daemon/ldm.mli
+++ b/daemon/ldm.mli
@@ -16,5 +16,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
+val available : unit -> bool
+
 val list_ldm_volumes : unit -> string list
 val list_ldm_partitions : unit -> string list
diff --git a/daemon/listfs.ml b/daemon/listfs.ml
new file mode 100644
index 000000000..df5404f81
--- /dev/null
+++ b/daemon/listfs.ml
@@ -0,0 +1,156 @@
+(* guestfs-inspection
+ * Copyright (C) 2009-2017 Red Hat 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 2 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+open Printf
+
+open Std_utils
+
+let rec list_filesystems () =
+  let has_lvm2 = Lvm.available () in
+  let has_ldm = Ldm.available () in
+
+  let devices = Devsparts.list_devices () in
+  let partitions = Devsparts.list_partitions () in
+  let mds = Md.list_md_devices () in
+
+  (* Look to see if any devices directly contain filesystems
+   * (RHBZ#590167).  However vfs-type will fail to tell us anything
+   * useful about devices which just contain partitions, so we also
+   * get the list of partitions and exclude the corresponding devices
+   * by using part-to-dev.
+   *)
+  let devices = List.fold_left (
+    fun devices part ->
+      let d = Devsparts.part_to_dev part in
+      List.filter ((<>) d) devices
+  ) devices partitions in
+
+  (* Use vfs-type to check for filesystems on devices. *)
+  let ret = filter_map check_with_vfs_type devices in
+
+  (* Use vfs-type to check for filesystems on partitions, but
+   * ignore MBR partition type 42 used by LDM.
+   *)
+  let ret =
+    ret @
+      filter_map (
+        fun part ->
+          if not has_ldm || not (is_mbr_partition_type_42 part) then
+            check_with_vfs_type part
+          else
+            None                (* ignore type 42 *)
+      ) partitions in
+
+  (* Use vfs-type to check for filesystems on md devices. *)
+  let ret = ret @ filter_map check_with_vfs_type mds in
+
+  (* LVM. *)
+  let ret =
+    if has_lvm2 then (
+      let lvs = Lvm.lvs () in
+      (* Use vfs-type to check for filesystems on LVs. *)
+      ret @ filter_map check_with_vfs_type lvs
+    )
+    else ret in
+
+  (* LDM. *)
+  let ret =
+    if has_ldm then (
+      let ldmvols = Ldm.list_ldm_volumes () in
+      let ldmparts = Ldm.list_ldm_partitions () in
+      (* Use vfs-type to check for filesystems on Windows dynamic disks. *)
+      ret @
+        filter_map check_with_vfs_type ldmvols @
+        filter_map check_with_vfs_type ldmparts
+    )
+    else ret in
+
+  List.flatten ret
+
+(* Use vfs-type to check for a filesystem of some sort of [device].
+ * Returns [Some [device, vfs_type; ...]] if found (there may be
+ * multiple devices found in the case of btrfs), else [None] if nothing
+ * is found.
+ *)
+and check_with_vfs_type device =
+  let mountable = Mountable.of_device device in
+  let vfs_type =
+    try Blkid.vfs_type mountable
+    with exn ->
+       if verbose () then
+         eprintf "check_with_vfs_type: %s: %s\n"
+                 device (Printexc.to_string exn);
+       "" in
+
+  if vfs_type = "" then
+    Some [mountable, "unknown"]
+
+  (* Ignore all "*_member" strings.  In libblkid these are returned
+   * for things which are members of some RAID or LVM set, most
+   * importantly "LVM2_member" which is a PV.
+   *)
+  else if String.is_suffix vfs_type "_member" then
+    None
+
+  (* Ignore LUKS-encrypted partitions.  These are also containers, as above. *)
+  else if vfs_type = "crypto_LUKS" then
+    None
+
+  (* A single btrfs device can turn into many volumes. *)
+  else if vfs_type = "btrfs" then (
+    let vols = Btrfs.btrfs_subvolume_list mountable in
+
+    (* Filter out the default subvolume.  You can access that by
+     * simply mounting the whole device, so we will add the whole
+     * device at the beginning of the returned list instead.
+     *)
+    let default_volume = Btrfs.btrfs_subvolume_get_default mountable in
+    let vols =
+      List.filter (
+        fun { Btrfs.btrfssubvolume_id = id } -> id <> default_volume
+      ) vols in
+
+    Some (
+      (mountable, vfs_type) (* whole device = default volume *)
+      :: List.map (
+           fun { Btrfs.btrfssubvolume_path = path } ->
+             let mountable = Mountable.of_btrfsvol device path in
+             (mountable, "btrfs")
+         ) vols
+      )
+  )
+
+  else
+    Some [mountable, vfs_type]
+
+(* We should ignore partitions that have MBR type byte 0x42, because
+ * these are members of a Windows dynamic disk group.  Trying to read
+ * them will cause errors (RHBZ#887520).  Assuming that libguestfs was
+ * compiled with ldm support, we'll get the filesystems on these later.
+ *)
+and is_mbr_partition_type_42 partition =
+  try
+    let partnum = Devsparts.part_to_partnum partition in
+    let device = Devsparts.part_to_dev partition in
+    let mbr_id = Parted.part_get_mbr_id device partnum in
+    mbr_id = 0x42
+  with exn ->
+     if verbose () then
+       eprintf "is_mbr_partition_type_42: %s: %s\n"
+               partition (Printexc.to_string exn);
+     false
diff --git a/daemon/listfs.mli b/daemon/listfs.mli
new file mode 100644
index 000000000..69958da77
--- /dev/null
+++ b/daemon/listfs.mli
@@ -0,0 +1,19 @@
+(* guestfs-inspection
+ * Copyright (C) 2009-2017 Red Hat 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 2 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+val list_filesystems : unit -> (Mountable.t * string) list
diff --git a/daemon/lvm.ml b/daemon/lvm.ml
index 55421b628..14f0a8578 100644
--- a/daemon/lvm.ml
+++ b/daemon/lvm.ml
@@ -22,6 +22,9 @@ open Std_utils
 
 open Utils
 
+external available : unit -> bool =
+  "guestfs_int_daemon_optgroup_lvm2_available" "noalloc"
+
 let lvs_has_S_opt = lazy (
   let out = command "lvm" ["lvs"; "--help"] in
   String.find out "-S" >= 0
diff --git a/daemon/lvm.mli b/daemon/lvm.mli
index f254728cb..1cf61ecfb 100644
--- a/daemon/lvm.mli
+++ b/daemon/lvm.mli
@@ -16,4 +16,6 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  *)
 
+val available : unit -> bool
+
 val lvs : unit -> string list
diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES
index 9562aed89..71e350764 100644
--- a/docs/C_SOURCE_FILES
+++ b/docs/C_SOURCE_FILES
@@ -321,7 +321,6 @@ lib/launch.c
 lib/libvirt-auth.c
 lib/libvirt-domain.c
 lib/libvirt-is-version.c
-lib/listfs.c
 lib/lpj.c
 lib/match.c
 lib/mountable.c
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
index bd3c21d3b..d5946b3f5 100644
--- a/generator/actions_core.ml
+++ b/generator/actions_core.ml
@@ -209,43 +209,6 @@ If the mountable does not represent a btrfs subvolume, then
 this function fails and the C<errno> is set to C<EINVAL>." };
 
   { defaults with
-    name = "list_filesystems"; added = (1, 5, 15);
-    style = RHashtable (RMountable, RPlainString, "fses"), [], [];
-    shortdesc = "list filesystems";
-    longdesc = "\
-This inspection command looks for filesystems on partitions,
-block devices and logical volumes, returning a list of C<mountables>
-containing filesystems and their type.
-
-The return value is a hash, where the keys are the devices
-containing filesystems, and the values are the filesystem types.
-For example:
-
- \"/dev/sda1\" => \"ntfs\"
- \"/dev/sda2\" => \"ext2\"
- \"/dev/vg_guest/lv_root\" => \"ext4\"
- \"/dev/vg_guest/lv_swap\" => \"swap\"
-
-The key is not necessarily a block device. It may also be an opaque
-‘mountable’ string which can be passed to C<guestfs_mount>.
-
-The value can have the special value \"unknown\", meaning the
-content of the device is undetermined or empty.
-\"swap\" means a Linux swap partition.
-
-This command runs other libguestfs commands, which might include
-C<guestfs_mount> and C<guestfs_umount>, and therefore you should
-use this soon after launch and only when nothing is mounted.
-
-Not all of the filesystems returned will be mountable.  In
-particular, swap partitions are returned in the list.  Also
-this command does not check that each filesystem
-found is valid and mountable, and some filesystems might
-be mountable but require special options.  Filesystems may
-not all belong to a single logical operating system
-(use C<guestfs_inspect_os> to look for OSes)." };
-
-  { defaults with
     name = "add_drive"; added = (0, 0, 3);
     style = RErr, [String (PlainString, "filename")], [OBool "readonly"; OString "format"; OString "iface"; OString "name"; OString "label"; OString "protocol"; OStringList "server"; OString "username"; OString "secret"; OString "cachemode"; OString "discard"; OBool "copyonread"];
     once_had_no_optargs = true;
@@ -9635,4 +9598,42 @@ initrd or kernel module(s) instead.
 
 =back" };
 
+  { defaults with
+    name = "list_filesystems"; added = (1, 5, 15);
+    style = RHashtable (RMountable, RPlainString, "fses"), [], [];
+    impl = OCaml "Listfs.list_filesystems";
+    shortdesc = "list filesystems";
+    longdesc = "\
+This inspection command looks for filesystems on partitions,
+block devices and logical volumes, returning a list of C<mountables>
+containing filesystems and their type.
+
+The return value is a hash, where the keys are the devices
+containing filesystems, and the values are the filesystem types.
+For example:
+
+ \"/dev/sda1\" => \"ntfs\"
+ \"/dev/sda2\" => \"ext2\"
+ \"/dev/vg_guest/lv_root\" => \"ext4\"
+ \"/dev/vg_guest/lv_swap\" => \"swap\"
+
+The key is not necessarily a block device. It may also be an opaque
+‘mountable’ string which can be passed to C<guestfs_mount>.
+
+The value can have the special value \"unknown\", meaning the
+content of the device is undetermined or empty.
+\"swap\" means a Linux swap partition.
+
+This command runs other libguestfs commands, which might include
+C<guestfs_mount> and C<guestfs_umount>, and therefore you should
+use this soon after launch and only when nothing is mounted.
+
+Not all of the filesystems returned will be mountable.  In
+particular, swap partitions are returned in the list.  Also
+this command does not check that each filesystem
+found is valid and mountable, and some filesystems might
+be mountable but require special options.  Filesystems may
+not all belong to a single logical operating system
+(use C<guestfs_inspect_os> to look for OSes)." };
+
 ]
diff --git a/generator/daemon.ml b/generator/daemon.ml
index 83994e9d3..66b625388 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -573,6 +573,58 @@ return_string_list (value retv)
   return take_stringsbuf (&ret); /* caller frees */
 }
 
+/* Implement RString (RMountable, _). */
+static char *
+return_string_mountable (value retv)
+{
+  value typev = Field (retv, 0);
+  value devicev = Field (retv, 1);
+  value subvolv;
+  char *ret;
+
+  if (Is_long (typev)) {      /* MountableDevice or MountablePath */
+    ret = strdup (String_val (devicev));
+    if (ret == NULL)
+      reply_with_perror (\"strdup\");
+    return ret;
+  }
+  else {                      /* MountableBtrfsVol of subvol */
+    subvolv = Field (typev, 0);
+    if (asprintf (&ret, \"btrfsvol:%%s/%%s\",
+                        String_val (devicev), String_val (subvolv)) == -1)
+      reply_with_perror (\"asprintf\");
+    return ret;
+  }
+}
+
+/* Implement RHashtable (RMountable, RPlainString, _). */
+static char **
+return_hashtable_mountable_string (value retv)
+{
+  CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (ret);
+  value v, mv, sv;
+  char *m;
+
+  while (retv != Val_int (0)) {
+    v = Field (retv, 0);        /* (Mountable.t, string) */
+    mv = Field (v, 0);          /* Mountable.t */
+    m = return_string_mountable (mv);
+    if (m == NULL)
+      return NULL;
+    if (add_string_nodup (&ret, m) == -1)
+      return NULL;
+    sv = Field (v, 1);          /* string */
+    if (add_string (&ret, String_val (sv)) == -1)
+      return NULL;
+    retv = Field (retv, 1);
+  }
+
+  if (end_stringsbuf (&ret) == -1)
+    return NULL;
+
+  return take_stringsbuf (&ret); /* caller frees */
+}
+
 ";
 
   (* Implement code for returning structs and struct lists. *)
@@ -810,7 +862,9 @@ return_string_list (value retv)
           pr "    CAMLreturnT (char *, NULL);\n";
           pr "  }\n";
           pr "  CAMLreturnT (char *, ret); /* caller frees */\n"
-       | RString _ -> assert false
+       | RString (RMountable, _) ->
+          pr "  char *ret = return_string_mountable (retv);\n";
+          pr "  CAMLreturnT (char *, ret); /* caller frees */\n"
        | RStringList _ ->
           pr "  char **ret = return_string_list (retv);\n";
           pr "  CAMLreturnT (char **, ret); /* caller frees */\n"
@@ -824,6 +878,9 @@ return_string_list (value retv)
           pr "    return_%s_list (retv);\n" typ;
           pr "  /* caller frees */\n";
           pr "  CAMLreturnT (guestfs_int_%s_list *, ret);\n" typ
+       | RHashtable (RMountable, RPlainString, _) ->
+          pr "  char **ret = return_hashtable_mountable_string (retv);\n";
+          pr "  CAMLreturnT (char **, ret); /* caller frees */\n"
        | RHashtable _ -> assert false
        | RBufferOut _ -> assert false
       );
diff --git a/generator/proc_nr.ml b/generator/proc_nr.ml
index 1b0feae87..dec02f5fa 100644
--- a/generator/proc_nr.ml
+++ b/generator/proc_nr.ml
@@ -483,6 +483,7 @@ let proc_nr = [
 473, "yara_destroy";
 474, "internal_yara_scan";
 475, "file_architecture";
+476, "list_filesystems";
 ]
 
 (* End of list.  If adding a new entry, add it at the end of the list
diff --git a/lib/MAX_PROC_NR b/lib/MAX_PROC_NR
index 7573eff88..b86395733 100644
--- a/lib/MAX_PROC_NR
+++ b/lib/MAX_PROC_NR
@@ -1 +1 @@
-475
+476
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 71dc25b9b..7eaff88ee 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -107,7 +107,6 @@ libguestfs_la_SOURCES = \
 	launch-unix.c \
 	libvirt-auth.c \
 	libvirt-domain.c \
-	listfs.c \
 	lpj.c \
 	match.c \
 	mountable.c \
diff --git a/lib/listfs.c b/lib/listfs.c
deleted file mode 100644
index 60aff3305..000000000
--- a/lib/listfs.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/* libguestfs
- * Copyright (C) 2010 Red Hat Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "guestfs.h"
-#include "guestfs-internal.h"
-#include "guestfs-internal-actions.h"
-#include "structs-cleanups.h"
-
-/* List filesystems.
- *
- * The current implementation just uses guestfs_vfs_type and doesn't
- * try mounting anything, but we reserve the right in future to try
- * mounting filesystems.
- */
-
-static void remove_from_list (char **list, const char *item);
-static int check_with_vfs_type (guestfs_h *g, const char *dev, struct stringsbuf *sb);
-static int is_mbr_partition_type_42 (guestfs_h *g, const char *partition);
-
-char **
-guestfs_impl_list_filesystems (guestfs_h *g)
-{
-  size_t i;
-  DECLARE_STRINGSBUF (ret);
-
-  const char *lvm2[] = { "lvm2", NULL };
-  const int has_lvm2 = guestfs_feature_available (g, (char **) lvm2);
-  const char *ldm[] = { "ldm", NULL };
-  const int has_ldm = guestfs_feature_available (g, (char **) ldm);
-
-  CLEANUP_FREE_STRING_LIST char **devices = NULL;
-  CLEANUP_FREE_STRING_LIST char **partitions = NULL;
-  CLEANUP_FREE_STRING_LIST char **mds = NULL;
-  CLEANUP_FREE_STRING_LIST char **lvs = NULL;
-  CLEANUP_FREE_STRING_LIST char **ldmvols = NULL;
-  CLEANUP_FREE_STRING_LIST char **ldmparts = NULL;
-
-  /* Look to see if any devices directly contain filesystems
-   * (RHBZ#590167).  However vfs-type will fail to tell us anything
-   * useful about devices which just contain partitions, so we also
-   * get the list of partitions and exclude the corresponding devices
-   * by using part-to-dev.
-   */
-  devices = guestfs_list_devices (g);
-  if (devices == NULL) goto error;
-  partitions = guestfs_list_partitions (g);
-  if (partitions == NULL) goto error;
-  mds = guestfs_list_md_devices (g);
-  if (mds == NULL) goto error;
-
-  for (i = 0; partitions[i] != NULL; ++i) {
-    CLEANUP_FREE char *dev = guestfs_part_to_dev (g, partitions[i]);
-    if (dev)
-      remove_from_list (devices, dev);
-  }
-
-  /* Use vfs-type to check for filesystems on devices. */
-  for (i = 0; devices[i] != NULL; ++i)
-    if (check_with_vfs_type (g, devices[i], &ret) == -1)
-      goto error;
-
-  /* Use vfs-type to check for filesystems on partitions. */
-  for (i = 0; partitions[i] != NULL; ++i) {
-    if (has_ldm == 0 || ! is_mbr_partition_type_42 (g, partitions[i])) {
-      if (check_with_vfs_type (g, partitions[i], &ret) == -1)
-        goto error;
-    }
-  }
-
-  /* Use vfs-type to check for filesystems on md devices. */
-  for (i = 0; mds[i] != NULL; ++i)
-    if (check_with_vfs_type (g, mds[i], &ret) == -1)
-      goto error;
-
-  if (has_lvm2 > 0) {
-    /* Use vfs-type to check for filesystems on LVs. */
-    lvs = guestfs_lvs (g);
-    if (lvs == NULL) goto error;
-
-    for (i = 0; lvs[i] != NULL; ++i)
-      if (check_with_vfs_type (g, lvs[i], &ret) == -1)
-        goto error;
-  }
-
-  if (has_ldm > 0) {
-    /* Use vfs-type to check for filesystems on Windows dynamic disks. */
-    ldmvols = guestfs_list_ldm_volumes (g);
-    if (ldmvols == NULL) goto error;
-
-    for (i = 0; ldmvols[i] != NULL; ++i)
-      if (check_with_vfs_type (g, ldmvols[i], &ret) == -1)
-        goto error;
-
-    ldmparts = guestfs_list_ldm_partitions (g);
-    if (ldmparts == NULL) goto error;
-
-    for (i = 0; ldmparts[i] != NULL; ++i)
-      if (check_with_vfs_type (g, ldmparts[i], &ret) == -1)
-        goto error;
-  }
-
-  /* Finish off the list and return it. */
-  guestfs_int_end_stringsbuf (g, &ret);
-  return ret.argv;
-
- error:
-  guestfs_int_free_stringsbuf (&ret);
-  return NULL;
-}
-
-/* If 'item' occurs in 'list', remove and free it. */
-static void
-remove_from_list (char **list, const char *item)
-{
-  size_t i;
-
-  for (i = 0; list[i] != NULL; ++i)
-    if (STREQ (list[i], item)) {
-      free (list[i]);
-      for (; list[i+1] != NULL; ++i)
-        list[i] = list[i+1];
-      list[i] = NULL;
-      return;
-    }
-}
-
-/* Use vfs-type to look for a filesystem of some sort on 'dev'.
- * Apart from some types which we ignore, add the result to the
- * 'ret' string list.
- */
-static int
-check_with_vfs_type (guestfs_h *g, const char *device, struct stringsbuf *sb)
-{
-  const char *v;
-  CLEANUP_FREE char *vfs_type = NULL;
-
-  guestfs_push_error_handler (g, NULL, NULL);
-  vfs_type = guestfs_vfs_type (g, device);
-  guestfs_pop_error_handler (g);
-
-  if (!vfs_type)
-    v = "unknown";
-  else if (STREQ (vfs_type, ""))
-    v = "unknown";
-  else if (STREQ (vfs_type, "btrfs")) {
-    CLEANUP_FREE_BTRFSSUBVOLUME_LIST struct guestfs_btrfssubvolume_list *vols =
-      guestfs_btrfs_subvolume_list (g, device);
-
-    if (vols == NULL)
-      return -1;
-
-    const int64_t default_volume =
-      guestfs_btrfs_subvolume_get_default (g, device);
-
-    for (size_t i = 0; i < vols->len; i++) {
-      struct guestfs_btrfssubvolume *this = &vols->val[i];
-
-      /* Ignore the default subvolume.  We get it by simply mounting
-       * the whole device of this btrfs filesystem.
-       */
-      if (this->btrfssubvolume_id == (uint64_t) default_volume)
-        continue;
-
-      guestfs_int_add_sprintf (g, sb,
-			       "btrfsvol:%s/%s",
-			       device, this->btrfssubvolume_path);
-      guestfs_int_add_string (g, sb, "btrfs");
-    }
-
-    v = vfs_type;
-  }
-  else {
-    /* Ignore all "*_member" strings.  In libblkid these are returned
-     * for things which are members of some RAID or LVM set, most
-     * importantly "LVM2_member" which is a PV.
-     */
-    const size_t n = strlen (vfs_type);
-    if (n >= 7 && STREQ (&vfs_type[n-7], "_member"))
-      return 0;
-
-    /* Ignore LUKS-encrypted partitions.  These are also containers. */
-    if (STREQ (vfs_type, "crypto_LUKS"))
-      return 0;
-
-    v = vfs_type;
-  }
-
-  guestfs_int_add_string (g, sb, device);
-  guestfs_int_add_string (g, sb, v);
-
-  return 0;
-}
-
-/* We should ignore partitions that have MBR type byte 0x42, because
- * these are members of a Windows dynamic disk group.  Trying to read
- * them will cause errors (RHBZ#887520).  Assuming that libguestfs was
- * compiled with ldm support, we'll get the filesystems on these later.
- */
-static int
-is_mbr_partition_type_42 (guestfs_h *g, const char *partition)
-{
-  CLEANUP_FREE char *device = NULL;
-  int partnum;
-  int mbr_id;
-  int ret = 0;
-
-  guestfs_push_error_handler (g, NULL, NULL);
-
-  partnum = guestfs_part_to_partnum (g, partition);
-  if (partnum == -1)
-    goto out;
-
-  device = guestfs_part_to_dev (g, partition);
-  if (device == NULL)
-    goto out;
-
-  mbr_id = guestfs_part_get_mbr_id (g, device, partnum);
-
-  ret = mbr_id == 0x42;
-
- out:
-  guestfs_pop_error_handler (g);
-
-  return ret;
-}
-- 
2.13.0




More information about the Libguestfs mailing list