[libvirt] [PATCH v1 09/15] qemu_firmware: Introduce qemuFirmwareFetchConfigs

Michal Privoznik mprivozn at redhat.com
Wed Feb 27 10:04:41 UTC 2019


Implementation for yet another part of firmware description
specification. This one covers selecting which files to parse.

There are three locations from which description files can be
loaded. In order of preference, from most generic to most
specific these are:

  /usr/share/qemu/firmware
  /etc/qemu/firmware
  $XDG_CONFIG_HOME/qemu/firmware

If a file is find in two or more locations then the most specific
one is used. Moreover, if file is empty then it means it is
overriding some generic description and disabling it.

Again, this is described in more details and with nice examples
in firmware.json specification.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/qemu/qemu_firmware.c | 127 +++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_firmware.h |   3 +
 2 files changed, 130 insertions(+)

diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
index e709a5f608..509927b154 100644
--- a/src/qemu/qemu_firmware.c
+++ b/src/qemu/qemu_firmware.c
@@ -21,9 +21,11 @@
 #include <config.h>
 
 #include "qemu_firmware.h"
+#include "configmake.h"
 #include "qemu_capabilities.h"
 #include "virarch.h"
 #include "virfile.h"
+#include "virhash.h"
 #include "virjson.h"
 #include "virlog.h"
 #include "virstring.h"
@@ -899,3 +901,128 @@ qemuFirmwareFormat(qemuFirmwarePtr fw)
 
     return virJSONValueToString(doc, true);
 }
+
+
+static int
+qemuFirmwareBuildFileList(virHashTablePtr files, const char *dir)
+{
+    DIR *dirp;
+    struct dirent *ent = NULL;
+    int rc;
+    int ret = -1;
+
+    if ((rc = virDirOpenIfExists(&dirp, dir)) < 0)
+        return -1;
+
+    if (rc == 0)
+        return 0;
+
+    while ((rc = virDirRead(dirp, &ent, dir)) > 0) {
+        VIR_AUTOFREE(char *) filename = NULL;
+        VIR_AUTOFREE(char *) path = NULL;
+
+        if (ent->d_type != DT_REG && ent->d_type != DT_LNK)
+            continue;
+
+        if (STRPREFIX(ent->d_name, "."))
+            continue;
+
+        if (VIR_STRDUP(filename, ent->d_name) < 0)
+            goto cleanup;
+
+        if (virAsprintf(&path, "%s/%s", dir, filename) < 0)
+            goto cleanup;
+
+        if (virHashUpdateEntry(files, filename, path) < 0)
+            goto cleanup;
+
+        path = NULL;
+    }
+
+    if (rc < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    virDirClose(&dirp);
+    return ret;
+}
+
+static int
+qemuFirmwareFilesSorter(const virHashKeyValuePair *a,
+                        const virHashKeyValuePair *b)
+{
+    return strcmp(a->key, b->key);
+}
+
+#define QEMU_FIRMWARE_SYSTEM_LOCATION PREFIX "/share/qemu/firmware"
+#define QEMU_FIRMWARE_ETC_LOCATION SYSCONFDIR "/qemu/firmware"
+
+int
+qemuFirmwareFetchConfigs(char ***firmwares)
+{
+    VIR_AUTOPTR(virHashTable) files = NULL;
+    VIR_AUTOFREE(char *) homeConfig = NULL;
+    VIR_AUTOFREE(char *) xdgConfig = NULL;
+    VIR_AUTOFREE(virHashKeyValuePairPtr) pairs = NULL;
+    virHashKeyValuePairPtr tmp = NULL;
+
+    *firmwares = NULL;
+
+    if (VIR_STRDUP(xdgConfig, virGetEnvBlockSUID("XDG_CONFIG_HOME")) < 0)
+        return -1;
+
+    if (!xdgConfig) {
+        VIR_AUTOFREE(char *) home = virGetUserDirectory();
+
+        if (!home)
+            return -1;
+
+        if (virAsprintf(&xdgConfig, "%s/.config", home) < 0)
+            return -1;
+    }
+
+    if (virAsprintf(&homeConfig, "%s/qemu/firmware", xdgConfig) < 0)
+        return -1;
+
+    if (!(files = virHashCreate(10, virHashValueFree)))
+        return -1;
+
+    if (qemuFirmwareBuildFileList(files, QEMU_FIRMWARE_SYSTEM_LOCATION) < 0)
+        return -1;
+
+    if (qemuFirmwareBuildFileList(files, QEMU_FIRMWARE_ETC_LOCATION) < 0)
+        return -1;
+
+    if (qemuFirmwareBuildFileList(files, homeConfig) < 0)
+        return -1;
+
+    if (virHashSize(files) == 0)
+        return 0;
+
+    if (!(pairs = virHashGetItems(files, qemuFirmwareFilesSorter)))
+        return -1;
+
+    for (tmp = pairs; tmp->key; tmp++) {
+        const char *path = tmp->value;
+        off_t len;
+
+        if ((len = virFileLength(path, -1)) < 0) {
+            virReportSystemError(errno,
+                                 _("unable to get size of %s"),
+                                 path);
+            return -1;
+        }
+
+        VIR_DEBUG("firmware description path '%s' len=%zd",
+                  path, (ssize_t) len);
+
+        if (len == 0)
+            continue;
+
+        if (virStringListAdd(firmwares, path) < 0)
+            return -1;
+    }
+
+    return 0;
+}
diff --git a/src/qemu/qemu_firmware.h b/src/qemu/qemu_firmware.h
index 952615d42b..321169f56c 100644
--- a/src/qemu/qemu_firmware.h
+++ b/src/qemu/qemu_firmware.h
@@ -37,4 +37,7 @@ qemuFirmwareParse(const char *path);
 char *
 qemuFirmwareFormat(qemuFirmwarePtr fw);
 
+int
+qemuFirmwareFetchConfigs(char ***firmwares);
+
 #endif /* LIBVIRT_QEMU_FIRMWARE_H */
-- 
2.19.2




More information about the libvir-list mailing list