summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard W.M. Jones <rjones@redhat.com>2010-11-25 15:38:26 +0000
committerRichard W.M. Jones <rjones@redhat.com>2010-11-25 15:40:56 +0000
commit4838ec3326d2970e6afe3cde6b368aeae840b969 (patch)
tree5adc185d8ee09f5f13162120d721f6b6d008086b
parent70faafe8d4f0c06c3e62c1e1469289255ee30c53 (diff)
downloadlibguestfs-4838ec3326d2970e6afe3cde6b368aeae840b969.tar.gz
libguestfs-4838ec3326d2970e6afe3cde6b368aeae840b969.tar.xz
libguestfs-4838ec3326d2970e6afe3cde6b368aeae840b969.zip
Export private function 'guestfs___for_each_disk' for use by virt-df.
This private function (not part of the API) allows us to iterate over disks from a guest, avoiding the business of writing all the XPath code yet again.
-rw-r--r--generator/generator_c.ml4
-rw-r--r--src/virt.c132
2 files changed, 91 insertions, 45 deletions
diff --git a/generator/generator_c.ml b/generator/generator_c.ml
index d0a47024..449f748f 100644
--- a/generator/generator_c.ml
+++ b/generator/generator_c.ml
@@ -545,6 +545,9 @@ extern void *guestfs_get_private (guestfs_h *g, const char *key);
extern void *guestfs_safe_malloc (guestfs_h *g, size_t nbytes);
extern void *guestfs_safe_calloc (guestfs_h *g, size_t n, size_t s);
extern const char *guestfs_tmpdir (void);
+#ifdef GUESTFS_PRIVATE_FOR_EACH_DISK
+extern int guestfs___for_each_disk (guestfs_h *g, virDomainPtr dom, int (*)(guestfs_h *g, const char *filename, const char *format, void *data), void *data);
+#endif
/* End of private functions. */
#ifdef __cplusplus
@@ -1287,6 +1290,7 @@ and generate_linker_script () =
"guestfs_safe_strdup";
"guestfs_safe_memdup";
"guestfs_tmpdir";
+ "guestfs___for_each_disk";
] in
let functions =
List.flatten (
diff --git a/src/virt.c b/src/virt.c
index ab38c36d..2c6be3c6 100644
--- a/src/virt.c
+++ b/src/virt.c
@@ -33,6 +33,8 @@
#include <libxml/tree.h>
#endif
+#define GUESTFS_PRIVATE_FOR_EACH_DISK 1
+
#include "guestfs.h"
#include "guestfs-internal.h"
#include "guestfs-internal-actions.h"
@@ -116,40 +118,28 @@ guestfs__add_domain (guestfs_h *g, const char *domain_name,
return r;
}
-/* This was proposed as an external API, but it's not quite baked yet. */
-static int
-guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom,
- const struct guestfs___add_libvirt_dom_argv *optargs)
+/* This function is also used in virt-df to avoid having all that
+ * stupid XPath code repeated. This is something that libvirt should
+ * really provide.
+ *
+ * The callback function 'f' is called once for each disk.
+ *
+ * Returns number of disks, or -1 if there was an error.
+ */
+int
+guestfs___for_each_disk (guestfs_h *g,
+ virDomainPtr dom,
+ int (*f) (guestfs_h *g,
+ const char *filename, const char *format,
+ void *data),
+ void *data)
{
- int r = -1, nr_added = 0, i;
+ int i, nr_added = 0, r = -1;
virErrorPtr err;
xmlDocPtr doc = NULL;
xmlXPathContextPtr xpathCtx = NULL;
xmlXPathObjectPtr xpathObj = NULL;
char *xml = NULL;
- int readonly;
- const char *iface;
- int cmdline_pos;
-
- cmdline_pos = guestfs___checkpoint_cmdline (g);
-
- readonly = optargs->bitmask & GUESTFS___ADD_LIBVIRT_DOM_READONLY_BITMASK
- ? optargs->readonly : 0;
- iface = optargs->bitmask & GUESTFS___ADD_LIBVIRT_DOM_IFACE_BITMASK
- ? optargs->iface : NULL;
-
- if (!readonly) {
- virDomainInfo info;
- if (virDomainGetInfo (dom, &info) == -1) {
- err = virGetLastError ();
- error (g, _("error getting domain info: %s"), err->message);
- goto cleanup;
- }
- if (info.state != VIR_DOMAIN_SHUTOFF) {
- error (g, _("error: domain is a live virtual machine.\nYou must use readonly access because write access to a running virtual machine\ncan cause disk corruption."));
- goto cleanup;
- }
- }
/* Domain XML. */
xml = virDomainGetXMLDesc (dom, 0);
@@ -258,22 +248,11 @@ guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom,
format = (char *) xmlNodeListGetString (doc, attr->children, 1);
}
- /* Add the disk, with optional format. */
- struct guestfs_add_drive_opts_argv optargs2 = { .bitmask = 0 };
- if (readonly) {
- optargs2.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK;
- optargs2.readonly = readonly;
- }
- if (format) {
- optargs2.bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
- optargs2.format = format;
- }
- if (iface) {
- optargs2.bitmask |= GUESTFS_ADD_DRIVE_OPTS_IFACE_BITMASK;
- optargs2.iface = iface;
- }
-
- int t = guestfs__add_drive_opts (g, filename, &optargs2);
+ int t;
+ if (f)
+ t = f (g, filename, format, data);
+ else
+ t = 0;
xmlFree (filename);
xmlFree (format);
@@ -295,7 +274,6 @@ guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom,
r = nr_added;
cleanup:
- if (r == -1) guestfs___rollback_cmdline (g, cmdline_pos);
free (xml);
if (xpathObj) xmlXPathFreeObject (xpathObj);
if (xpathCtx) xmlXPathFreeContext (xpathCtx);
@@ -304,6 +282,70 @@ guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom,
return r;
}
+static int
+add_disk (guestfs_h *g, const char *filename, const char *format,
+ void *optargs_vp)
+{
+ struct guestfs_add_drive_opts_argv *optargs = optargs_vp;
+
+ if (format) {
+ optargs->bitmask |= GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
+ optargs->format = format;
+ } else
+ optargs->bitmask &= ~GUESTFS_ADD_DRIVE_OPTS_FORMAT_BITMASK;
+
+ return guestfs__add_drive_opts (g, filename, optargs);
+}
+
+/* This was proposed as an external API, but it's not quite baked yet. */
+static int
+guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom,
+ const struct guestfs___add_libvirt_dom_argv *optargs)
+{
+ int r = -1;
+ virErrorPtr err;
+ int cmdline_pos;
+
+ cmdline_pos = guestfs___checkpoint_cmdline (g);
+
+ int readonly =
+ optargs->bitmask & GUESTFS___ADD_LIBVIRT_DOM_READONLY_BITMASK
+ ? optargs->readonly : 0;
+ const char *iface =
+ optargs->bitmask & GUESTFS___ADD_LIBVIRT_DOM_IFACE_BITMASK
+ ? optargs->iface : NULL;
+
+ if (!readonly) {
+ virDomainInfo info;
+ if (virDomainGetInfo (dom, &info) == -1) {
+ err = virGetLastError ();
+ error (g, _("error getting domain info: %s"), err->message);
+ goto cleanup;
+ }
+ if (info.state != VIR_DOMAIN_SHUTOFF) {
+ error (g, _("error: domain is a live virtual machine.\nYou must use readonly access because write access to a running virtual machine\ncan cause disk corruption."));
+ goto cleanup;
+ }
+ }
+
+ /* Add the disks. */
+ struct guestfs_add_drive_opts_argv optargs2 = { .bitmask = 0 };
+ if (readonly) {
+ optargs2.bitmask |= GUESTFS_ADD_DRIVE_OPTS_READONLY_BITMASK;
+ optargs2.readonly = readonly;
+ }
+ if (iface) {
+ optargs2.bitmask |= GUESTFS_ADD_DRIVE_OPTS_IFACE_BITMASK;
+ optargs2.iface = iface;
+ }
+
+ r = guestfs___for_each_disk (g, dom, add_disk, &optargs2);
+
+ cleanup:
+ if (r == -1) guestfs___rollback_cmdline (g, cmdline_pos);
+ return r;
+}
+
#else /* no libvirt or libxml2 at compile time */
#define NOT_IMPL(r) \