[libvirt] [PATCH 05/12] Define public API for managing identities

Daniel P. Berrange berrange at redhat.com
Wed May 2 11:44:12 UTC 2012


From: "Daniel P. Berrange" <berrange at 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




More information about the libvir-list mailing list