From: "Daniel P. Berrange" <berrange(a)redhat.com>
---
include/libvirt/libvirt.h.in | 30 ++++++
include/libvirt/virterror.h | 1 +
src/datatypes.h | 20 ++++
src/libvirt.c | 246 ++++++++++++++++++++++++++++++++++++++++++
src/libvirt_public.syms | 5 +
src/util/virterror.c | 6 ++
6 files changed, 308 insertions(+)
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index ac5df95..86a9514 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1088,6 +1088,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 7283207..e44390e 100644
--- a/include/libvirt/virterror.h
+++ b/include/libvirt/virterror.h
@@ -251,6 +251,7 @@ typedef enum {
VIR_ERR_MIGRATE_UNSAFE = 81, /* Migration is not safe */
VIR_ERR_OVERFLOW = 82, /* integer overflow */
VIR_ERR_BLOCK_COPY_ACTIVE = 83, /* action prevented by block copy job */
+ VIR_ERR_INVALID_IDENTITY = 84, /* Invalid identity pointer */
} virErrorNumber;
/**
diff --git a/src/datatypes.h b/src/datatypes.h
index fc284d2..b8d8db2 100644
--- a/src/datatypes.h
+++ b/src/datatypes.h
@@ -38,6 +38,16 @@
/**
+ * 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 cfd7711..a206800 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -1544,6 +1544,252 @@ virConnectRef(virConnectPtr conn)
return 0;
}
+
+/**
+ * virIdentityNew:
+ *
+ * Creates a new empty identity object. After creating, one or
+ * more identifying attributes should be set on the identity.
+ *
+ * Returns: a new empty identity
+ */
+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;
+}
+
+/**
+ * virIdentityRef:
+ * @ident: the identity to hold a reference on
+ *
+ * Increment the reference count on the identity. For each
+ * additional call to this method, there shall be a corresponding
+ * call to virIdentityFree to release the reference count, once
+ * the caller no longer needs the reference to this object.
+ *
+ * This method is typically useful for applications where multiple
+ * threads are using an identity object, and it is required that
+ * the identity remain around until all threads have finished using
+ * it. ie, each new thread using a identity would increment
+ * the reference count.
+ *
+ * Returns 0 in case of success and -1 in case of failure.
+ */
+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;
+}
+
+
+/**
+ * virIdentitySetAttr:
+ * @ident: the identity to modify
+ * @attr: the attribute type to set
+ * @value: the identifying value to associate with @attr
+ *
+ * Sets an identifying attribute @attr on @ident. Each
+ * @attr type can only be set once.
+ *
+ * Returns: 0 on success, or -1 on error
+ */
+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;
+}
+
+
+/**
+ * virIdentityGetAttr:
+ * @ident: the identity to query
+ * @attr: the attribute to read
+ * @value: filled with the attribute value
+ *
+ * Fills @value with a pointer to the value associated
+ * with the identifying attribute @attr in @ident. If
+ * @attr is not set, then it will simply be initialized
+ * to NULL and considered as a successful read
+ *
+ * Returns 0 on success, -1 on error
+ */
+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;
+}
+
+
+/**
+ * virIdentityIsEqual:
+ * @identA: the first identity
+ * @identB: the second identity
+ *
+ * Compares every attribute in @identA and @identB
+ * to determine if they refer to the same identity
+ *
+ * Returns 1 if they are equal, 0 if not equal or -1 on error
+ */
+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;
+}
+
+
+/**
+ * virIdentityFree:
+ * @ident: the identity to free
+ *
+ * Decrement the reference count on @ident. If the
+ * reference count hits zero, then the @ident object
+ * will be freed
+ *
+ * Returns number of references remaining, or -1 on error
+ */
+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/libvirt_public.syms b/src/libvirt_public.syms
index 46c13fb..35f11b8 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -527,6 +527,11 @@ LIBVIRT_0.9.10 {
virDomainShutdownFlags;
virStorageVolResize;
virStorageVolWipePattern;
+ virIdentityNew;
+ virIdentityIsEqual;
+ virIdentitySetAttr;
+ virIdentityGetAttr;
+ virIdentityFree;
} LIBVIRT_0.9.9;
LIBVIRT_0.9.11 {
diff --git a/src/util/virterror.c b/src/util/virterror.c
index b1a5d2b..33ef713 100644
--- a/src/util/virterror.c
+++ b/src/util/virterror.c
@@ -1259,6 +1259,12 @@ virErrorMsg(virErrorNumber error, const char *info)
else
errmsg = _("block copy still active: %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.10