From nobody Sun Feb 8 20:35:31 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1551950992352617.7456572202022; Thu, 7 Mar 2019 01:29:52 -0800 (PST) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6776A307E040; Thu, 7 Mar 2019 09:29:50 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 3C25719C68; Thu, 7 Mar 2019 09:29:50 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id EFBF53FB13; Thu, 7 Mar 2019 09:29:49 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x279TdrY009462 for ; Thu, 7 Mar 2019 04:29:39 -0500 Received: by smtp.corp.redhat.com (Postfix) id 7B7355C5FD; Thu, 7 Mar 2019 09:29:39 +0000 (UTC) Received: from moe.brq.redhat.com (unknown [10.43.2.30]) by smtp.corp.redhat.com (Postfix) with ESMTP id CB8E65C28C; Thu, 7 Mar 2019 09:29:38 +0000 (UTC) From: Michal Privoznik To: libvir-list@redhat.com Date: Thu, 7 Mar 2019 10:29:19 +0100 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-loop: libvir-list@redhat.com Cc: lersek@redhat.com Subject: [libvirt] [PATCH v2 09/15] qemu_firmware: Introduce qemuFirmwareFetchConfigs X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.42]); Thu, 07 Mar 2019 09:29:50 +0000 (UTC) Content-Type: text/plain; charset="utf-8" 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 Reviewed-by: Laszlo Ersek --- 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 =20 #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) =20 return virJSONValueToString(doc, true); } + + +static int +qemuFirmwareBuildFileList(virHashTablePtr files, const char *dir) +{ + DIR *dirp; + struct dirent *ent =3D NULL; + int rc; + int ret =3D -1; + + if ((rc =3D virDirOpenIfExists(&dirp, dir)) < 0) + return -1; + + if (rc =3D=3D 0) + return 0; + + while ((rc =3D virDirRead(dirp, &ent, dir)) > 0) { + VIR_AUTOFREE(char *) filename =3D NULL; + VIR_AUTOFREE(char *) path =3D NULL; + + if (ent->d_type !=3D DT_REG && ent->d_type !=3D 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 =3D NULL; + } + + if (rc < 0) + goto cleanup; + + ret =3D 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 =3D NULL; + VIR_AUTOFREE(char *) homeConfig =3D NULL; + VIR_AUTOFREE(char *) xdgConfig =3D NULL; + VIR_AUTOFREE(virHashKeyValuePairPtr) pairs =3D NULL; + virHashKeyValuePairPtr tmp =3D NULL; + + *firmwares =3D NULL; + + if (VIR_STRDUP(xdgConfig, virGetEnvBlockSUID("XDG_CONFIG_HOME")) < 0) + return -1; + + if (!xdgConfig) { + VIR_AUTOFREE(char *) home =3D 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 =3D 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 filenam= es + * where each filename (as key) has the highest priority full pathname + * associated with it. */ + + if (virHashSize(files) =3D=3D 0) + return 0; + + if (!(pairs =3D virHashGetItems(files, qemuFirmwareFilesSorter))) + return -1; + + for (tmp =3D pairs; tmp->key; tmp++) { + const char *path =3D tmp->value; + off_t len; + + if ((len =3D virFileLength(path, -1)) < 0) { + virReportSystemError(errno, + _("unable to get size of '%s'"), + path); + return -1; + } + + VIR_DEBUG("firmware description path '%s' len=3D%jd", + path, (intmax_t) len); + + if (len =3D=3D 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); =20 +int +qemuFirmwareFetchConfigs(char ***firmwares); + #endif /* LIBVIRT_QEMU_FIRMWARE_H */ --=20 2.19.2 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list