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@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 */
--
2.19.2
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On Thu, Mar 07, 2019 at 10:29:19AM +0100, 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@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;
I wonder if it really makes sense to read /root/ for this. Normally we would
only look at the home config for unprivileged daemon, eg we don't look in
/root for finding PKI x509 certs IIRC.
Regards,
Daniel
--
|: https://berrange.com -o- https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o- https://fstop138.berrange.com :|
|: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On 3/7/19 12:55 PM, Daniel P. Berrangé wrote:
> On Thu, Mar 07, 2019 at 10:29:19AM +0100, 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@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;
>
> I wonder if it really makes sense to read /root/ for this. Normally we would
> only look at the home config for unprivileged daemon, eg we don't look in
> /root for finding PKI x509 certs IIRC.
Fair enough. Root is able to put configs into /etc/qemu/firmware
anyways. Will fix this locally for now.
Michal
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
On 03/07/19 13:46, Michal Privoznik wrote:
> On 3/7/19 12:55 PM, Daniel P. Berrangé wrote:
>> On Thu, Mar 07, 2019 at 10:29:19AM +0100, 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@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;
>>
>> I wonder if it really makes sense to read /root/ for this. Normally we
>> would
>> only look at the home config for unprivileged daemon, eg we don't look in
>> /root for finding PKI x509 certs IIRC.
>
> Fair enough. Root is able to put configs into /etc/qemu/firmware
> anyways. Will fix this locally for now.
Please carry forward my R-b, given up-thread, when you implement the
tweak suggested by Dan.
Thanks
Laszlo
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
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@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@redhat.com>
--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list
© 2016 - 2026 Red Hat, Inc.