On 05/02/2012 07:44 AM, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> --- 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);
Do you want to use %u instead of %d here?
+ + 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;
Do you need to add virIdentityRef here too? -- Regards, Corey
} 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; }
-- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list