[Libguestfs] [PATCH 1/4] qemu: Add a function to test if -bios feature is supported.

Richard W.M. Jones rjones at redhat.com
Wed May 25 16:37:52 UTC 2016


This has to read the data dirs from qemu using the new 'qemu -L ?'
flag added in qemu 2.7.
---
 src/guestfs-internal.h |  1 +
 src/qemu.c             | 90 +++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 83 insertions(+), 8 deletions(-)

diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 03f1034..2df29bf 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -922,6 +922,7 @@ struct qemu_data;
 extern struct qemu_data *guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version);
 extern int guestfs_int_qemu_supports (guestfs_h *g, const struct qemu_data *, const char *option);
 extern int guestfs_int_qemu_supports_device (guestfs_h *g, const struct qemu_data *, const char *device_name);
+extern int guestfs_int_qemu_supports_bios (guestfs_h *g, const struct qemu_data *, const char *bios_name);
 extern int guestfs_int_qemu_supports_virtio_scsi (guestfs_h *g, struct qemu_data *, const struct version *qemu_version);
 extern char *guestfs_int_drive_source_qemu_param (guestfs_h *g, const struct drive_source *src);
 extern bool guestfs_int_discard_possible (guestfs_h *g, struct drive *drv, const struct version *qemu_version);
diff --git a/src/qemu.c b/src/qemu.c
index 11bf5cf..73ab8b4 100644
--- a/src/qemu.c
+++ b/src/qemu.c
@@ -48,11 +48,12 @@
 COMPILE_REGEXP (re_major_minor, "(\\d+)\\.(\\d+)", 0)
 
 struct qemu_data {
-  char *qemu_help;              /* Output of qemu -help. */
-  char *qemu_devices;           /* Output of qemu -device ? */
+  char *qemu_help;            /* Output of qemu -help. */
+  char *qemu_devices;         /* Output of qemu -device ? */
+  char *qemu_datadirs;        /* Output of qemu -L ? (NULL if not supported) */
 
-  int virtio_scsi;              /* See function
-                                   guestfs_int_qemu_supports_virtio_scsi */
+  int virtio_scsi;            /* See function
+                                 guestfs_int_qemu_supports_virtio_scsi */
 };
 
 static int test_qemu (guestfs_h *g, struct qemu_data *data, struct version *qemu_version);
@@ -68,8 +69,9 @@ static void read_all (guestfs_h *g, void *retv, const char *buf, size_t len);
 
 /**
  * Test qemu binary (or wrapper) runs, and do C<qemu -help> so we know
- * the version of qemu what options this qemu supports, and
- * C<qemu -device ?> so we know what devices are available.
+ * the version of qemu what options this qemu supports,
+ * C<qemu -device ?> so we know what devices are available,
+ * and C<qemu -L ?> to list data directories.
  *
  * The version number of qemu (from the C<-help> output) is saved in
  * C<&qemu_version>.
@@ -83,7 +85,8 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version)
   struct qemu_data *data;
   struct stat statbuf;
   CLEANUP_FREE char *cachedir = NULL, *qemu_stat_filename = NULL,
-    *qemu_help_filename = NULL, *qemu_devices_filename = NULL;
+    *qemu_help_filename = NULL, *qemu_devices_filename = NULL,
+    *qemu_datadirs_filename = NULL;
   FILE *fp;
   int generation;
   uint64_t prev_size, prev_mtime;
@@ -100,6 +103,7 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version)
   qemu_stat_filename = safe_asprintf (g, "%s/qemu.stat", cachedir);
   qemu_help_filename = safe_asprintf (g, "%s/qemu.help", cachedir);
   qemu_devices_filename = safe_asprintf (g, "%s/qemu.devices", cachedir);
+  qemu_datadirs_filename = safe_asprintf (g, "%s/qemu.datadirs", cachedir);
 
   /* Did we previously test the same version of qemu? */
   debug (g, "checking for previously cached test results of %s, in %s",
@@ -122,7 +126,8 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version)
      * and qemu -devices ? output.
      */
     if (access (qemu_help_filename, R_OK) == -1 ||
-        access (qemu_devices_filename, R_OK) == -1)
+        access (qemu_devices_filename, R_OK) == -1 ||
+        access (qemu_datadirs_filename, R_OK) == -1)
       goto do_test;
 
     debug (g, "loading previously cached test results");
@@ -143,6 +148,12 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version)
       return NULL;
     }
 
+    if (guestfs_int_read_whole_file (g, qemu_datadirs_filename,
+                                     &data->qemu_datadirs, NULL) == -1) {
+      guestfs_int_free_qemu_data (data);
+      return NULL;
+    }
+
     return data;
   }
 
@@ -183,6 +194,19 @@ guestfs_int_test_qemu (guestfs_h *g, struct version *qemu_version)
   if (fclose (fp) == -1)
     goto devices_error;
 
+  fp = fopen (qemu_datadirs_filename, "w");
+  if (fp == NULL) {
+  datadirs_error:
+    perrorf (g, "%s", qemu_datadirs_filename);
+    if (fp != NULL) fclose (fp);
+    guestfs_int_free_qemu_data (data);
+    return NULL;
+  }
+  if (fprintf (fp, "%s", data->qemu_datadirs) == -1)
+    goto datadirs_error;
+  if (fclose (fp) == -1)
+    goto datadirs_error;
+
   /* Write the qemu.stat file last so that its presence indicates that
    * the qemu.help and qemu.devices files ought to exist.
    */
@@ -214,6 +238,7 @@ test_qemu (guestfs_h *g, struct qemu_data *data, struct version *qemu_version)
 {
   CLEANUP_CMD_CLOSE struct command *cmd1 = guestfs_int_new_command (g);
   CLEANUP_CMD_CLOSE struct command *cmd2 = guestfs_int_new_command (g);
+  CLEANUP_CMD_CLOSE struct command *cmd3 = guestfs_int_new_command (g);
   int r;
 
   guestfs_int_cmd_add_arg (cmd1, g->hv);
@@ -247,6 +272,28 @@ test_qemu (guestfs_h *g, struct qemu_data *data, struct version *qemu_version)
   if (r == -1 || !WIFEXITED (r) || WEXITSTATUS (r) != 0)
     goto error;
 
+  /* qemu -L ? only supported in qemu >= 2.7 */
+  if (guestfs_int_version_ge (qemu_version, 2, 7, 0)) {
+    guestfs_int_cmd_add_arg (cmd3, g->hv);
+    guestfs_int_cmd_add_arg (cmd3, "-display");
+    guestfs_int_cmd_add_arg (cmd3, "none");
+    guestfs_int_cmd_add_arg (cmd3, "-machine");
+    guestfs_int_cmd_add_arg (cmd3,
+#ifdef MACHINE_TYPE
+                             MACHINE_TYPE ","
+#endif
+                             "accel=kvm:tcg");
+    guestfs_int_cmd_add_arg (cmd3, "-L");
+    guestfs_int_cmd_add_arg (cmd3, "?");
+    guestfs_int_cmd_set_stdout_callback (cmd3, read_all, &data->qemu_datadirs,
+                                         CMD_STDOUT_FLAG_WHOLE_BUFFER);
+    r = guestfs_int_cmd_run (cmd3);
+    if (r == -1 || !WIFEXITED (r) || WEXITSTATUS (r) != 0)
+      goto error;
+  }
+  else
+    data->qemu_datadirs = safe_strdup (g, "");
+
   return 0;
 
  error:
@@ -321,6 +368,32 @@ guestfs_int_qemu_supports_device (guestfs_h *g,
   return strstr (data->qemu_devices, device_name) != NULL;
 }
 
+/**
+ * Test if a named BIOS is supported by qemu.
+ */
+int
+guestfs_int_qemu_supports_bios (guestfs_h *g,
+                                const struct qemu_data *data,
+                                const char *bios_name)
+{
+  CLEANUP_FREE_STRING_LIST char **datadirs;
+  size_t i;
+
+  datadirs = guestfs_int_split_string ('\n', data->qemu_datadirs);
+  if (datadirs == NULL)
+    return 0;          /* ignore errors, return false which is safe */
+
+  for (i = 0; datadirs[i] != NULL; ++i) {
+    CLEANUP_FREE char *path;
+
+    path = safe_asprintf (g, "%s/%s", datadirs[i], bios_name);
+    if (access (path, R_OK) == 0)
+      return 1;
+  }
+
+  return 0;
+}
+
 static int
 old_or_broken_virtio_scsi (const struct version *qemu_version)
 {
@@ -706,6 +779,7 @@ guestfs_int_free_qemu_data (struct qemu_data *data)
   if (data) {
     free (data->qemu_help);
     free (data->qemu_devices);
+    free (data->qemu_datadirs);
     free (data);
   }
 }
-- 
2.7.4




More information about the Libguestfs mailing list