[libvirt] [PATCH 07/17] virudev: Introduce virUdevMgrDump

Michal Privoznik mprivozn at redhat.com
Wed Oct 26 12:36:54 UTC 2016


Now that we are able to store security labels for devices, next
step is to flush them into a file. For more convenience I've
chosen JSON format (as we have all the APIs needed for processing
the format).

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 po/POTFILES.in           |   1 +
 src/libvirt_private.syms |   2 +
 src/util/virudev.c       | 157 +++++++++++++++++++++++++++++++++++++++++++++++
 src/util/virudev.h       |   5 ++
 4 files changed, 165 insertions(+)

diff --git a/po/POTFILES.in b/po/POTFILES.in
index 1469240..dabc612 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -248,6 +248,7 @@ src/util/virthreadpool.c
 src/util/virtime.c
 src/util/virtpm.c
 src/util/virtypedparam.c
+src/util/virudev.c
 src/util/viruri.c
 src/util/virusb.c
 src/util/virutil.c
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 184317a..b465a0d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2575,6 +2575,8 @@ virTypedParamsValidate;
 
 # util/virudev.h
 virUdevMgrAddLabel;
+virUdevMgrDumpFile;
+virUdevMgrDumpStr;
 virUdevMgrNew;
 virUdevMgrRemoveAllLabels;
 
diff --git a/src/util/virudev.c b/src/util/virudev.c
index f4799e7..7f52149 100644
--- a/src/util/virudev.c
+++ b/src/util/virudev.c
@@ -24,7 +24,9 @@
 
 #include "internal.h"
 #include "viralloc.h"
+#include "virfile.h"
 #include "virhash.h"
+#include "virjson.h"
 #include "virobject.h"
 #include "virudev.h"
 
@@ -112,6 +114,68 @@ udevSeclabelUpdate(udevSeclabelPtr list,
 }
 
 
+static virJSONValuePtr
+udevSeclabelDump(const virSecurityDeviceLabelDef *seclabel)
+{
+    virJSONValuePtr object;
+
+    if (!(object = virJSONValueNewObject()) ||
+        virJSONValueObjectAppendString(object, "model", seclabel->model) < 0 ||
+        virJSONValueObjectAppendString(object, "label", seclabel->label) < 0)
+        goto error;
+
+    return object;
+
+ error:
+    virJSONValueFree(object);
+    return NULL;
+}
+
+
+static int
+udevSeclabelsDump(void *payload,
+                  const void *name,
+                  void *opaque)
+{
+    udevSeclabelPtr list = payload;
+    const char *device = name;
+    virJSONValuePtr seclabels = opaque;
+    virJSONValuePtr deviceLabels = NULL;
+    virJSONValuePtr deviceJSON = NULL;
+    size_t i;
+    int ret = -1;
+
+    if (!(deviceLabels = virJSONValueNewArray()))
+        return ret;
+
+    for (i = 0; i < list->nseclabels; i++) {
+        virJSONValuePtr seclabel = udevSeclabelDump(list->seclabels[i]);
+
+        if (!seclabel ||
+            virJSONValueArrayAppend(deviceLabels, seclabel) < 0) {
+            virJSONValueFree(seclabel);
+            goto cleanup;
+        }
+    }
+
+    if (!(deviceJSON = virJSONValueNewObject()) ||
+        virJSONValueObjectAppendString(deviceJSON, "device", device) < 0 ||
+        virJSONValueObjectAppend(deviceJSON, "labels", deviceLabels) < 0)
+        goto cleanup;
+    deviceLabels = NULL;
+
+    if (virJSONValueArrayAppend(seclabels, deviceJSON) < 0)
+        goto cleanup;
+    deviceJSON = NULL;
+
+    ret = 0;
+ cleanup:
+    virJSONValueFree(deviceJSON);
+    virJSONValueFree(deviceLabels);
+    return ret;
+}
+
+
 static void
 virUdevMgrDispose(void *obj)
 {
@@ -202,3 +266,96 @@ virUdevMgrRemoveAllLabels(virUdevMgrPtr mgr,
     virObjectUnlock(mgr);
     return ret;
 }
+
+
+static virJSONValuePtr
+virUdevSeclabelDump(virUdevMgrPtr mgr)
+{
+    virJSONValuePtr seclabels;
+
+    if (!(seclabels = virJSONValueNewArray()))
+        return NULL;
+
+    if (virHashForEach(mgr->labels, udevSeclabelsDump, seclabels) < 0) {
+        virJSONValueFree(seclabels);
+        return NULL;
+    }
+
+    return seclabels;
+}
+
+
+static char *
+virUdevMgrDumpInternal(virUdevMgrPtr mgr)
+{
+    virJSONValuePtr object = NULL;
+    virJSONValuePtr child = NULL;
+    char *ret = NULL;
+
+    if (!(object = virJSONValueNewObject()))
+        goto cleanup;
+
+    if (!(child = virUdevSeclabelDump(mgr)))
+        goto cleanup;
+
+    if (virJSONValueObjectAppend(object, "labels", child) < 0) {
+        virJSONValueFree(child);
+        goto cleanup;
+    }
+
+    ret = virJSONValueToString(object, true);
+ cleanup:
+    virJSONValueFree(object);
+    return ret;
+}
+
+
+char *
+virUdevMgrDumpStr(virUdevMgrPtr mgr)
+{
+    char *ret;
+
+    virObjectLock(mgr);
+    ret = virUdevMgrDumpInternal(mgr);
+    virObjectUnlock(mgr);
+    return ret;
+}
+
+
+static int
+virUdevMgrRewriter(int fd, void *opaque)
+{
+    const char *str = opaque;
+
+    return safewrite(fd, str, strlen(str));
+}
+
+
+int
+virUdevMgrDumpFile(virUdevMgrPtr mgr,
+                   const char *filename)
+{
+    int ret = -1;
+    char *state;
+
+    virObjectLock(mgr);
+
+    if (!(state = virUdevMgrDumpInternal(mgr)))
+        goto cleanup;
+
+    /* Here we shouldn't use pure virFileWriteStr() as that one is not atomic.
+     * We can be interrupted in the middle (e.g. due to a context switch) and
+     * thus leave the file partially written. */
+    if (virFileRewrite(filename, 0644, virUdevMgrRewriter, state) < 0) {
+        virReportSystemError(errno,
+                             _("Unable to save state file %s"),
+                             filename);
+        goto cleanup;
+    }
+
+    ret = 0;
+ cleanup:
+    virObjectUnlock(mgr);
+    VIR_FREE(state);
+    return ret;
+}
diff --git a/src/util/virudev.h b/src/util/virudev.h
index 692b39b..1d5a23e 100644
--- a/src/util/virudev.h
+++ b/src/util/virudev.h
@@ -36,4 +36,9 @@ int virUdevMgrAddLabel(virUdevMgrPtr mgr,
 int virUdevMgrRemoveAllLabels(virUdevMgrPtr mgr,
                               const char *device);
 
+char *virUdevMgrDumpStr(virUdevMgrPtr mgr);
+
+int virUdevMgrDumpFile(virUdevMgrPtr mgr,
+                       const char *filename);
+
 #endif
-- 
2.8.4




More information about the libvir-list mailing list