From: "Daniel P. Berrange" <berrange(a)redhat.com>
---
include/libvirt/libvirt.h.in | 30 +++++++
include/libvirt/virterror.h | 1 +
src/datatypes.h | 22 +++++-
src/libvirt.c | 176 ++++++++++++++++++++++++++++++++++++++++++
src/util/virterror.c | 6 ++
5 files changed, 234 insertions(+), 1 deletions(-)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index e436f3c..967a925 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1020,6 +1020,36 @@ typedef virConnectAuth *virConnectAuthPtr;
VIR_EXPORT_VAR virConnectAuthPtr virConnectAuthPtrDefault;
+typedef struct _virIdentity virIdentity;
+typedef virIdentity *virIdentityPtr;
+
+typedef enum {
+ VIR_IDENTITY_ATTR_UNIX_USER_NAME,
+ VIR_IDENTITY_ATTR_UNIX_GROUP_NAME,
+ VIR_IDENTITY_ATTR_UNIX_PROCESS_ID,
+ VIR_IDENTITY_ATTR_SASL_USER_NAME,
+ VIR_IDENTITY_ATTR_X509_DISTINGUISHED_NAME,
+ VIR_IDENTITY_ATTR_SECURITY_CONTEXT,
+
+ VIR_IDENTITY_ATTR_LAST,
+} virIdentityAttrType;
+
+
+virIdentityPtr virIdentityNew(void);
+int virIdentityRef(virIdentityPtr ident);
+int virIdentitySetAttr(virIdentityPtr ident,
+ unsigned int attr,
+ const char *value);
+
+int virIdentityGetAttr(virIdentityPtr ident,
+ unsigned int attr,
+ const char **value);
+
+int virIdentityIsEqual(virIdentityPtr identA,
+ virIdentityPtr identB);
+
+int virIdentityFree(virIdentityPtr ident);
+
/**
* VIR_UUID_BUFLEN:
*
diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h
index e896d67..6db31d8 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -243,6 +243,7 @@ typedef enum {
risky domain snapshot revert */
VIR_ERR_OPERATION_ABORTED = 78, /* operation on a domain was
canceled/aborted by user */
+ VIR_ERR_INVALID_IDENTITY = 79, /* Invalid identity pointer */
} virErrorNumber;
/**
diff --git a/src/datatypes.h b/src/datatypes.h
index 91b1bfd..3cf3097 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -31,13 +31,23 @@
* VIR_CONNECT_MAGIC:
*
* magic value used to protect the API when pointers to connection structures
- * are passed down by the uers.
+ * are passed down by the users.
*/
# define VIR_CONNECT_MAGIC 0x4F23DEAD
# define VIR_IS_CONNECT(obj) ((obj) && (obj)->magic==VIR_CONNECT_MAGIC)
/**
+ * VIR_IDENTITY_MAGIC:
+ *
+ * magic value used to protect the API when pointers to identity structures
+ * are passed down by the users.
+ */
+# define VIR_IDENTITY_MAGIC 0xB33FCAF3
+# define VIR_IS_IDENTITY(obj) ((obj) && (obj)->magic==VIR_IDENTITY_MAGIC)
+
+
+/**
* VIR_DOMAIN_MAGIC:
*
* magic value used to protect the API when pointers to domain structures
@@ -190,6 +200,16 @@ struct _virConnect {
int refs; /* reference count */
};
+
+struct _virIdentity {
+ unsigned int magic;
+ virMutex lock;
+ int refs;
+
+ char *attrs[VIR_IDENTITY_ATTR_LAST];
+};
+
+
/**
* _virDomain:
*
diff --git a/src/libvirt.c b/src/libvirt.c
index 7b8adf7..4ced8b9 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -1510,6 +1510,182 @@ virConnectRef(virConnectPtr conn)
return 0;
}
+
+virIdentityPtr virIdentityNew(void)
+{
+ virIdentityPtr ident;
+
+ if (VIR_ALLOC(ident) < 0) {
+ virReportOOMError();
+ return NULL;
+ }
+
+ if (virMutexInit(&ident->lock) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to initialize mutex"));
+ VIR_FREE(ident);
+ return NULL;
+ }
+ ident->magic = VIR_IDENTITY_MAGIC;
+ ident->refs = 1;
+
+ return ident;
+}
+
+int virIdentityRef(virIdentityPtr ident)
+{
+ if ((!VIR_IS_IDENTITY(ident))) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ virMutexLock(&ident->lock);
+ VIR_DEBUG("ident=%p refs=%d", ident, ident->refs);
+ ident->refs++;
+ virMutexUnlock(&ident->lock);
+ return 0;
+}
+
+int virIdentitySetAttr(virIdentityPtr ident,
+ unsigned int attr,
+ const char *value)
+{
+ VIR_DEBUG("ident=%p attribute=%u value=%s", ident, attr, NULLSTR(value));
+
+ if ((!VIR_IS_IDENTITY(ident))) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ if (attr >= VIR_IDENTITY_ATTR_LAST) {
+ virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ if (!value) {
+ virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ virMutexLock(&ident->lock);
+
+ if (ident->attrs[attr]) {
+ virLibConnError(VIR_ERR_OPERATION_DENIED, "%s",
+ _("Identity attribute is already set"));
+ goto error;
+ }
+
+ if (!(ident->attrs[attr] = strdup(value))) {
+ virReportOOMError();
+ goto error;
+ }
+
+ virMutexUnlock(&ident->lock);
+ return 0;
+
+error:
+ virDispatchError(NULL);
+ virMutexUnlock(&ident->lock);
+ return -1;
+}
+
+
+int virIdentityGetAttr(virIdentityPtr ident,
+ unsigned int attr,
+ const char **value)
+{
+ VIR_DEBUG("ident=%p attribute=%d value=%p", ident, attr, value);
+
+ if ((!VIR_IS_IDENTITY(ident))) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ if (attr >= VIR_IDENTITY_ATTR_LAST) {
+ virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+
+ virMutexLock(&ident->lock);
+ *value = ident->attrs[attr];
+ virMutexUnlock(&ident->lock);
+ return 0;
+}
+
+
+int virIdentityIsEqual(virIdentityPtr identA,
+ virIdentityPtr identB)
+{
+ VIR_DEBUG("identA=%p identB=%p", identA, identB);
+ int ret = 0;
+ size_t i;
+
+ if ((!VIR_IS_IDENTITY(identA))) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ if ((!VIR_IS_IDENTITY(identB))) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ virMutexLock(&identA->lock);
+ virMutexLock(&identB->lock);
+
+ for (i = 0 ; i < VIR_IDENTITY_ATTR_LAST ; i++) {
+ if (identA->attrs[i] == NULL &&
+ identB->attrs[i] != NULL)
+ goto cleanup;
+ if (identA->attrs[i] != NULL &&
+ identB->attrs[i] == NULL)
+ goto cleanup;
+ if (STRNEQ(identA->attrs[i],
+ identB->attrs[i]))
+ goto cleanup;
+ }
+
+ ret = 1;
+cleanup:
+ virMutexUnlock(&identA->lock);
+ virMutexUnlock(&identB->lock);
+ return ret;
+}
+
+
+int virIdentityFree(virIdentityPtr ident)
+{
+ size_t i;
+
+ if ((!VIR_IS_IDENTITY(ident))) {
+ virLibConnError(VIR_ERR_INVALID_CONN, __FUNCTION__);
+ virDispatchError(NULL);
+ return -1;
+ }
+ virMutexLock(&ident->lock);
+ VIR_DEBUG("ident=%p refs=%d", ident, ident->refs);
+ ident->refs--;
+ if (ident->refs > 0) {
+ int ret = ident->refs;
+ virMutexUnlock(&ident->lock);
+ return ret;
+ }
+ for (i = 0 ; i < VIR_IDENTITY_ATTR_LAST ; i++)
+ VIR_FREE(ident->attrs[i]);
+
+ virMutexUnlock(&ident->lock);
+ virMutexDestroy(&ident->lock);
+ VIR_FREE(ident);
+ return 0;
+}
+
+
+
/*
* Not for public use. This function is part of the internal
* implementation of driver features in the remote case.
diff --git a/src/util/virterror.c b/src/util/virterror.c
index 380dc56..701aa2f 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -1219,6 +1219,12 @@ virErrorMsg(virErrorNumber error, const char *info)
else
errmsg = _("operation aborted: %s");
break;
+ case VIR_ERR_INVALID_IDENTITY:
+ if (info == NULL)
+ errmsg = _("invalid identity pointer in");
+ else
+ errmsg = _("invalid identity pointer in %s");
+ break;
}
return (errmsg);
}
--
1.7.7.5