This also reimplements the lv_canonical function in OCaml. We cannot
call the original C function because it calls reply_with_perror which
would break the OCaml bindings.
---
daemon/Makefile.am | 3 +-
daemon/findfs.c | 92 -----------------------------------------------
daemon/findfs.ml | 56 +++++++++++++++++++++++++++++
daemon/findfs.mli | 20 +++++++++++
daemon/lvm.ml | 28 +++++++++++++++
daemon/lvm.mli | 10 ++++++
docs/C_SOURCE_FILES | 1 -
generator/actions_core.ml | 2 ++
8 files changed, 118 insertions(+), 94 deletions(-)
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index e3517ca15..eb8bbb152 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -95,7 +95,6 @@ guestfsd_SOURCES = \
ext2.c \
fallocate.c \
file.c \
- findfs.c \
fill.c \
find.c \
format.c \
@@ -249,6 +248,7 @@ SOURCES_MLI = \
devsparts.mli \
file.mli \
filearch.mli \
+ findfs.mli \
is.mli \
ldm.mli \
link.mli \
@@ -278,6 +278,7 @@ SOURCES_ML = \
ldm.ml \
link.ml \
lvm.ml \
+ findfs.ml \
md.ml \
mount.ml \
parted.ml \
diff --git a/daemon/findfs.c b/daemon/findfs.c
deleted file mode 100644
index f44a60088..000000000
--- a/daemon/findfs.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* libguestfs - the guestfsd daemon
- * Copyright (C) 2010 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.
- */
-
-#include <config.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "daemon.h"
-#include "actions.h"
-
-static char *
-findfs (const char *tag, const char *label_or_uuid)
-{
- char *out;
- CLEANUP_FREE char *err = NULL;
- CLEANUP_FREE char *arg = NULL;
- int r;
- size_t len;
-
- /* Kill the cache file, forcing blkid to reread values from the
- * original filesystems. In blkid there is a '-p' option which is
- * supposed to do this, but (a) it doesn't work and (b) that option
- * is not supported in RHEL 5.
- */
- unlink ("/etc/blkid/blkid.tab");
- unlink ("/run/blkid/blkid.tab");
-
- if (asprintf (&arg, "%s=%s", tag, label_or_uuid) == -1) {
- reply_with_perror ("asprintf");
- return NULL;
- }
-
- r = command (&out, &err, "findfs", arg, NULL);
- if (r == -1) {
- reply_with_error ("%s", err);
- free (out);
- return NULL;
- }
-
- /* Trim trailing \n if present. */
- len = strlen (out);
- if (len > 0 && out[len-1] == '\n')
- out[len-1] = '\0';
-
- if (STRPREFIX (out, "/dev/mapper/") || STRPREFIX (out, "/dev/dm-"))
{
- char *canonical;
- r = lv_canonical (out, &canonical);
- if (r == -1) {
- free (out);
- return NULL;
- }
- if (r == 1) {
- free (out);
- out = canonical;
- }
- /* Ignore the case where r == 0. /dev/mapper does not correspond
- * to an LV, so the best we can do is just return it as-is.
- */
- }
-
- return out; /* caller frees */
-}
-
-char *
-do_findfs_uuid (const char *uuid)
-{
- return findfs ("UUID", uuid);
-}
-
-char *
-do_findfs_label (const char *label)
-{
- return findfs ("LABEL", label);
-}
diff --git a/daemon/findfs.ml b/daemon/findfs.ml
new file mode 100644
index 000000000..8acb72928
--- /dev/null
+++ b/daemon/findfs.ml
@@ -0,0 +1,56 @@
+(* 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 Unix
+
+open Std_utils
+
+open Utils
+
+let rec findfs_uuid uuid =
+ findfs "UUID" uuid
+and findfs_label label =
+ findfs "LABEL"label
+
+and findfs tag str =
+ (* Kill the cache file, forcing blkid to reread values from the
+ * original filesystems. In blkid there is a '-p' option which is
+ * supposed to do this, but (a) it doesn't work and (b) that option
+ * is not supported in RHEL 5.
+ *)
+ (try unlink "/etc/blkid/blkid.tab" with Unix_error _ -> ());
+ (try unlink "/run/blkid/blkid.tab" with Unix_error _ -> ());
+
+ let out = command "findfs" [ sprintf "%s=%s" tag str ] in
+
+ (* Trim trailing \n if present. *)
+ let out = String.trim out in
+
+ if String.is_prefix out "/dev/mapper/" ||
+ String.is_prefix out "/dev/dm-" then (
+ match Lvm.lv_canonical out with
+ | None ->
+ (* Ignore the case where 'out' doesn't appear to be an LV.
+ * The best we can do is return the original as-is.
+ *)
+ out
+ | Some out -> out
+ )
+ else
+ out
diff --git a/daemon/findfs.mli b/daemon/findfs.mli
new file mode 100644
index 000000000..acef0395c
--- /dev/null
+++ b/daemon/findfs.mli
@@ -0,0 +1,20 @@
+(* 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 findfs_uuid : string -> string
+val findfs_label : string -> string
diff --git a/daemon/lvm.ml b/daemon/lvm.ml
index 0d1dc55b5..4210c2fb3 100644
--- a/daemon/lvm.ml
+++ b/daemon/lvm.ml
@@ -16,6 +16,7 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*)
+open Unix
open Printf
open Std_utils
@@ -98,3 +99,30 @@ and filter_convert_old_lvs_output out =
) lines in
List.sort compare lines
+
+(* Convert a non-canonical LV path like /dev/mapper/vg-lv or /dev/dm-0
+ * to a canonical one.
+ *
+ * This is harder than it should be. A LV device like /dev/VG/LV is
+ * really a symlink to a device-mapper device like /dev/dm-0. However
+ * at the device-mapper (kernel) level, nothing is really known about
+ * LVM (a userspace concept). Therefore we use a convoluted method to
+ * determine this, by listing out known LVs and checking whether the
+ * rdev (major/minor) of the device we are passed matches any of them.
+ *
+ * Note use of 'stat' instead of 'lstat' so that symlinks are fully
+ * resolved.
+ *)
+let lv_canonical device =
+ let stat1 = stat device in
+ let lvs = lvs () in
+ try
+ Some (
+ List.find (
+ fun lv ->
+ let stat2 = stat lv in
+ stat1.st_rdev = stat2.st_rdev
+ ) lvs
+ )
+ with
+ | Not_found -> None
diff --git a/daemon/lvm.mli b/daemon/lvm.mli
index 1cf61ecfb..7cde16ebb 100644
--- a/daemon/lvm.mli
+++ b/daemon/lvm.mli
@@ -19,3 +19,13 @@
val available : unit -> bool
val lvs : unit -> string list
+
+val lv_canonical : string -> string option
+(** Convert a non-canonical LV path like /dev/mapper/vg-lv or /dev/dm-0
+ to a canonical one.
+
+ On error this raises an exception. There are two possible non-error
+ return cases:
+
+ Some lv = conversion was successful, returning the canonical LV
+ None = input path was not an LV, it could not be made canonical *)
diff --git a/docs/C_SOURCE_FILES b/docs/C_SOURCE_FILES
index b4f085699..d720f43ff 100644
--- a/docs/C_SOURCE_FILES
+++ b/docs/C_SOURCE_FILES
@@ -104,7 +104,6 @@ daemon/fallocate.c
daemon/file.c
daemon/fill.c
daemon/find.c
-daemon/findfs.c
daemon/format.c
daemon/fs-min-size.c
daemon/fsck.c
diff --git a/generator/actions_core.ml b/generator/actions_core.ml
index b1e2559e0..0a967f76d 100644
--- a/generator/actions_core.ml
+++ b/generator/actions_core.ml
@@ -5746,6 +5746,7 @@ returns true iff this is the case." };
{ defaults with
name = "findfs_uuid"; added = (1, 5, 3);
style = RString (RDevice, "device"), [String (PlainString,
"uuid")], [];
+ impl = OCaml "Findfs.findfs_uuid";
shortdesc = "find a filesystem by UUID";
longdesc = "\
This command searches the filesystems and returns the one
@@ -5757,6 +5758,7 @@ To find the UUID of a filesystem, use
C<guestfs_vfs_uuid>." };
{ defaults with
name = "findfs_label"; added = (1, 5, 3);
style = RString (RDevice, "device"), [String (PlainString,
"label")], [];
+ impl = OCaml "Findfs.findfs_label";
shortdesc = "find a filesystem by label";
longdesc = "\
This command searches the filesystems and returns the one
--
2.13.2