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