---
daemon/md.c | 66 -----------------------------------------------
daemon/md.ml | 37 ++++++++++++++++++++++++++
daemon/md.mli | 1 +
generator/actions_core.ml | 1 +
generator/daemon.ml | 27 +++++++++++++++++++
5 files changed, 66 insertions(+), 66 deletions(-)
diff --git a/daemon/md.c b/daemon/md.c
index 5c9ecd136..549dd89fa 100644
--- a/daemon/md.c
+++ b/daemon/md.c
@@ -218,72 +218,6 @@ do_md_create (const char *name, char *const *devices,
#pragma GCC diagnostic pop
#endif
-char **
-do_md_detail (const char *md)
-{
- size_t i;
- int r;
-
- CLEANUP_FREE char *out = NULL, *err = NULL;
- CLEANUP_FREE_STRING_LIST char **lines = NULL;
-
- CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (ret);
-
- const char *mdadm[] = { str_mdadm, "-D", "--export", md, NULL };
- r = commandv (&out, &err, mdadm);
- if (r == -1) {
- reply_with_error ("%s", err);
- return NULL;
- }
-
- /* Split the command output into lines */
- lines = split_lines (out);
- if (lines == NULL)
- return NULL;
-
- /* Parse the output of mdadm -D --export:
- * MD_LEVEL=raid1
- * MD_DEVICES=2
- * MD_METADATA=1.0
- * MD_UUID=cfa81b59:b6cfbd53:3f02085b:58f4a2e1
- * MD_NAME=localhost.localdomain:0
- */
- for (i = 0; lines[i] != NULL; ++i) {
- char *line = lines[i];
-
- /* Skip blank lines (shouldn't happen) */
- if (line[0] == '\0') continue;
-
- /* Split the line in 2 at the equals sign */
- char *eq = strchr (line, '=');
- if (eq) {
- *eq = '\0'; eq++;
-
- /* Remove the MD_ prefix from the key and translate the remainder to lower
- * case */
- if (STRPREFIX (line, "MD_")) {
- line += 3;
- for (char *j = line; *j != '\0'; j++) {
- *j = c_tolower (*j);
- }
- }
-
- /* Add the key/value pair to the output */
- if (add_string (&ret, line) == -1 ||
- add_string (&ret, eq) == -1) return NULL;
- } else {
- /* Ignore lines with no equals sign (shouldn't happen). Log to stderr so
- * it will show up in LIBGUESTFS_DEBUG. */
- fprintf (stderr, "md-detail: unexpected mdadm output ignored: %s",
line);
- }
- }
-
- if (end_stringsbuf (&ret) == -1)
- return NULL;
-
- return take_stringsbuf (&ret);
-}
-
int
do_md_stop (const char *md)
{
diff --git a/daemon/md.ml b/daemon/md.ml
index caf87cf8f..ba045b5f7 100644
--- a/daemon/md.ml
+++ b/daemon/md.ml
@@ -46,3 +46,40 @@ let list_md_devices () =
(* Return the list sorted. *)
sort_device_names devs
+
+let md_detail md =
+ let out = command "mdadm" ["-D"; "--export"; md] in
+
+ (* Split the command output into lines. *)
+ let out = String.trim out in
+ let lines = String.nsplit "\n" out in
+
+ (* Parse the output of mdadm -D --export:
+ * MD_LEVEL=raid1
+ * MD_DEVICES=2
+ * MD_METADATA=1.0
+ * MD_UUID=cfa81b59:b6cfbd53:3f02085b:58f4a2e1
+ * MD_NAME=localhost.localdomain:0
+ *)
+ filter_map (
+ fun line ->
+ (* Skip blank lines (shouldn't happen). *)
+ if line = "" then None
+ else (
+ (* Split the line at the equals sign. *)
+ let key, value = String.split "=" line in
+
+ (* Remove the MD_ prefix from the key and translate the
+ * remainder to lower case.
+ *)
+ let key =
+ if String.is_prefix key "MD_" then
+ String.sub key 3 (String.length key - 3)
+ else
+ key in
+ let key = String.lowercase_ascii key in
+
+ (* Add the key/value pair to the output. *)
+ Some (key, value)
+ )
+ ) lines
diff --git a/daemon/md.mli b/daemon/md.mli
index 56b6ea65e..8f0c79a7f 100644
--- a/daemon/md.mli
+++ b/daemon/md.mli
@@ -17,3 +17,4 @@
*)
val list_md_devices : unit -> string list
+val md_detail : string -> (string * string) list
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
index db1411ff8..070a1c641 100644
--- a/generator/actions_core.ml
+++ b/generator/actions_core.ml
@@ -6606,6 +6606,7 @@ List all Linux md devices." };
{ defaults with
name = "md_detail"; added = (1, 15, 6);
style = RHashtable (RPlainString, RPlainString, "info"), [String (Device,
"md")], [];
+ impl = OCaml "Md.md_detail";
optional = Some "mdadm";
shortdesc = "obtain metadata for an MD device";
longdesc = "\
diff --git a/generator/daemon.ml b/generator/daemon.ml
index 66b625388..f20c87bea 100644
--- a/generator/daemon.ml
+++ b/generator/daemon.ml
@@ -597,6 +597,30 @@ return_string_mountable (value retv)
}
}
+/* Implement RHashtable (RPlainString, RPlainString, _). */
+static char **
+return_hashtable_string_string (value retv)
+{
+ CLEANUP_FREE_STRINGSBUF DECLARE_STRINGSBUF (ret);
+ value v, sv;
+
+ while (retv != Val_int (0)) {
+ v = Field (retv, 0); /* (string, string) */
+ sv = Field (v, 0); /* string */
+ if (add_string (&ret, String_val (sv)) == -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 RHashtable (RMountable, RPlainString, _). */
static char **
return_hashtable_mountable_string (value retv)
@@ -878,6 +902,9 @@ return_hashtable_mountable_string (value retv)
pr " return_%s_list (retv);\n" typ;
pr " /* caller frees */\n";
pr " CAMLreturnT (guestfs_int_%s_list *, ret);\n" typ
+ | RHashtable (RPlainString, RPlainString, _) ->
+ pr " char **ret = return_hashtable_string_string (retv);\n";
+ pr " CAMLreturnT (char **, ret); /* caller frees */\n"
| RHashtable (RMountable, RPlainString, _) ->
pr " char **ret = return_hashtable_mountable_string (retv);\n";
pr " CAMLreturnT (char **, ret); /* caller frees */\n"
--
2.13.0