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

Laszlo Ersek lersek at redhat.com
Tue Mar 12 10:27:23 UTC 2019


On 03/07/19 10:29, Michal Privoznik wrote:
> 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 found 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 (qemu commit 3a0adfc9bf).
> 
> Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
> ---
>  src/qemu/qemu_firmware.c | 134 +++++++++++++++++++++++++++++++++++++++
>  src/qemu/qemu_firmware.h |   3 +
>  2 files changed, 137 insertions(+)
> 
> diff --git a/src/qemu/qemu_firmware.c b/src/qemu/qemu_firmware.c
> index 8f718ee2a6..a818f60c91 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,135 @@ 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;
> +
> +    /* At this point, the @files hash table contains unique set of filenames
> +     * where each filename (as key) has the highest priority full pathname
> +     * associated with it. */
> +
> +    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=%jd",
> +                  path, (intmax_t) len);
> +
> +        if (len == 0) {
> +            /* Empty files are used to mask less specific instances
> +             * of the same file. */
> +            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 */
> 

Thanks for addressing my comments!

Reviewed-by: Laszlo Ersek <lersek at redhat.com>




More information about the libvir-list mailing list