Export private function 'guestfs___for_each_disk' for use by virt-df.
authorRichard W.M. Jones <rjones@redhat.com>
Thu, 25 Nov 2010 15:38:26 +0000 (15:38 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Thu, 25 Nov 2010 15:40:56 +0000 (15:40 +0000)
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.

generator/generator_c.ml
src/virt.c

index d0a4702..449f748 100644 (file)
@@ -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);
 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
 /* End of private functions. */
 
 #ifdef __cplusplus
@@ -1287,6 +1290,7 @@ and generate_linker_script () =
     "guestfs_safe_strdup";
     "guestfs_safe_memdup";
     "guestfs_tmpdir";
     "guestfs_safe_strdup";
     "guestfs_safe_memdup";
     "guestfs_tmpdir";
+    "guestfs___for_each_disk";
   ] in
   let functions =
     List.flatten (
   ] in
   let functions =
     List.flatten (
index ab38c36..2c6be3c 100644 (file)
@@ -33,6 +33,8 @@
 #include <libxml/tree.h>
 #endif
 
 #include <libxml/tree.h>
 #endif
 
+#define GUESTFS_PRIVATE_FOR_EACH_DISK 1
+
 #include "guestfs.h"
 #include "guestfs-internal.h"
 #include "guestfs-internal-actions.h"
 #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;
 }
 
   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;
   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);
 
   /* 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);
     }
 
       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);
 
     xmlFree (filename);
     xmlFree (format);
@@ -295,7 +274,6 @@ guestfs___add_libvirt_dom (guestfs_h *g, virDomainPtr dom,
   r = nr_added;
 
  cleanup:
   r = nr_added;
 
  cleanup:
-  if (r == -1) guestfs___rollback_cmdline (g, cmdline_pos);
   free (xml);
   if (xpathObj) xmlXPathFreeObject (xpathObj);
   if (xpathCtx) xmlXPathFreeContext (xpathCtx);
   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;
 }
 
   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)                                                     \
 #else /* no libvirt or libxml2 at compile time */
 
 #define NOT_IMPL(r)                                                     \