diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/list.h | 238 | ||||
-rw-r--r-- | src/osi_common.c | 364 | ||||
-rw-r--r-- | src/osi_device.c | 675 | ||||
-rw-r--r-- | src/osi_filter.c | 358 | ||||
-rw-r--r-- | src/osi_hv.c | 396 | ||||
-rw-r--r-- | src/osi_internal_types.h | 181 | ||||
-rw-r--r-- | src/osi_lib.c | 328 | ||||
-rw-r--r-- | src/osi_os.c | 738 | ||||
-rw-r--r-- | src/osinfo_common.c | 349 | ||||
-rw-r--r-- | src/osinfo_dataread.c (renamed from src/osi_dataread.c) | 468 | ||||
-rw-r--r-- | src/osinfo_db.c | 555 | ||||
-rw-r--r-- | src/osinfo_device.c | 94 | ||||
-rw-r--r-- | src/osinfo_devicelist.c | 121 | ||||
-rw-r--r-- | src/osinfo_entity.c | 321 | ||||
-rw-r--r-- | src/osinfo_filter.c | 298 | ||||
-rw-r--r-- | src/osinfo_hypervisor.c | 122 | ||||
-rw-r--r-- | src/osinfo_hypervisorlist.c | 121 | ||||
-rw-r--r-- | src/osinfo_list.c | 219 | ||||
-rw-r--r-- | src/osinfo_os.c | 402 | ||||
-rw-r--r-- | src/osinfo_oslist.c | 121 |
20 files changed, 2929 insertions, 3540 deletions
diff --git a/src/list.h b/src/list.h deleted file mode 100644 index 1535cb8..0000000 --- a/src/list.h +++ /dev/null @@ -1,238 +0,0 @@ -/* This file is from Linux Kernel (include/linux/list.h) - * and modified by simply removing hardware prefetching of list items. - * Here by copyright, credits attributed to wherever they belong. - * Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu) - */ - -/* - * Simple doubly linked list implementation. - * - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - -struct list_head { - struct list_head *next, *prev; -}; - -#define LIST_HEAD_INIT(name) { &(name), &(name) } - -#define LIST_HEAD(name) \ - struct list_head name = LIST_HEAD_INIT(name) - -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) -{ - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; -} - -/** - * list_add - add a new entry - * @new: new entry to be added - * @head: list head to add it after - * - * Insert a new entry after the specified head. - * This is good for implementing stacks. - */ -static inline void list_add(struct list_head *new, struct list_head *head) -{ - __list_add(new, head, head->next); -} - -/** - * list_add_tail - add a new entry - * @new: new entry to be added - * @head: list head to add it before - * - * Insert a new entry before the specified head. - * This is useful for implementing queues. - */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) -{ - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head *prev, struct list_head *next) -{ - next->prev = prev; - prev->next = next; -} - -/** - * list_del - deletes entry from list. - * @entry: the element to delete from the list. - * Note: list_empty on entry does not return true after this, the entry is in an undefined state. - */ -static inline void list_del(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - entry->next = (void *) 0; - entry->prev = (void *) 0; -} - -/** - * list_del_init - deletes entry from list and reinitialize it. - * @entry: the element to delete from the list. - */ -static inline void list_del_init(struct list_head *entry) -{ - __list_del(entry->prev, entry->next); - INIT_LIST_HEAD(entry); -} - -/** - * list_move - delete from one list and add as another's head - * @list: the entry to move - * @head: the head that will precede our entry - */ -static inline void list_move(struct list_head *list, struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add(list, head); -} - -/** - * list_move_tail - delete from one list and add as another's tail - * @list: the entry to move - * @head: the head that will follow our entry - */ -static inline void list_move_tail(struct list_head *list, - struct list_head *head) -{ - __list_del(list->prev, list->next); - list_add_tail(list, head); -} - -/** - * list_empty - tests whether a list is empty - * @head: the list to test. - */ -static inline int list_empty(struct list_head *head) -{ - return head->next == head; -} - -static inline void __list_splice(struct list_head *list, - struct list_head *head) -{ - struct list_head *first = list->next; - struct list_head *last = list->prev; - struct list_head *at = head->next; - - first->prev = head; - head->next = first; - - last->next = at; - at->prev = last; -} - -/** - * list_splice - join two lists - * @list: the new list to add. - * @head: the place to add it in the first list. - */ -static inline void list_splice(struct list_head *list, struct list_head *head) -{ - if (!list_empty(list)) - __list_splice(list, head); -} - -/** - * list_splice_init - join two lists and reinitialise the emptied list. - * @list: the new list to add. - * @head: the place to add it in the first list. - * - * The list at @list is reinitialised - */ -static inline void list_splice_init(struct list_head *list, - struct list_head *head) -{ - if (!list_empty(list)) { - __list_splice(list, head); - INIT_LIST_HEAD(list); - } -} - -/** - * list_entry - get the struct for this entry - * @ptr: the &struct list_head pointer. - * @type: the type of the struct this is embedded in. - * @member: the name of the list_struct within the struct. - */ -#define list_entry(ptr, type, member) \ - ((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member))) - -/** - * list_for_each - iterate over a list - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); \ - pos = pos->next) -/** - * list_for_each_prev - iterate over a list backwards - * @pos: the &struct list_head to use as a loop counter. - * @head: the head for your list. - */ -#define list_for_each_prev(pos, head) \ - for (pos = (head)->prev; pos != (head); \ - pos = pos->prev) - -/** - * list_for_each_safe - iterate over a list safe against removal of list entry - * @pos: the &struct list_head to use as a loop counter. - * @n: another &struct list_head to use as temporary storage - * @head: the head for your list. - */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) - -/** - * list_for_each_entry - iterate over list of given type - * @pos: the type * to use as a loop counter. - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry(pos, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = list_entry(pos->member.next, typeof(*pos), member)) - -/** - * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry - * @pos: the type * to use as a loop counter. - * @n: another type * to use as temporary storage - * @head: the head for your list. - * @member: the name of the list_struct within the struct. - */ -#define list_for_each_entry_safe(pos, n, head, member) \ - for (pos = list_entry((head)->next, typeof(*pos), member), \ - n = list_entry(pos->member.next, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.next, typeof(*n), member)) diff --git a/src/osi_common.c b/src/osi_common.c deleted file mode 100644 index 7b33c4a..0000000 --- a/src/osi_common.c +++ /dev/null @@ -1,364 +0,0 @@ -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <libosinfo.h> -#include "list.h" -#include "osi_internal_types.h" - -void __osi_free_keyval(struct osi_keyval_multi * kv) -{ - struct list_head * cursor, * tmp; - struct osi_value * value; - - if (!kv) - return; - - list_for_each_safe(cursor, tmp, &kv->values_list) { - value = list_entry(cursor, struct osi_value, list); - list_del(cursor); - free(value->val); - free(value); - } - free(kv->key); - free(kv); -} - -struct osi_keyval_multi * __osi_find_kv(char* key, struct list_head * search_list) -{ - struct list_head * cursor; - struct osi_keyval_multi * kv; - - if (!key || !search_list) - return NULL; - - list_for_each (cursor, search_list) { - kv = list_entry(cursor, struct osi_keyval_multi, list); - if (strcmp(key, kv->key) == 0) - return kv; - } - return NULL; -} - -struct osi_keyval_multi * __osi_create_kv(char* key, struct list_head * dest_list) -{ - struct osi_keyval_multi * kv; - char* kv_key; - - if (!key || !dest_list) - return NULL; - - kv = malloc(sizeof(*kv)); - kv_key = strdup(key); - if (!kv || !kv_key) { - free(kv); - free(kv_key); - return NULL; - } - - kv->key = kv_key; - kv->num_values = 0; - INIT_LIST_HEAD(&kv->values_list); - list_add_tail(&kv->list, dest_list); - - return kv; -} - -struct osi_keyval_multi * __osi_find_or_create_kv(char* key, struct list_head * list, int* num) -{ - struct osi_keyval_multi * kv = __osi_find_kv(key, list); - if (!kv) { - kv = __osi_create_kv(key, list); - *num += 1; - } - return kv; -} - -int __osi_add_keyval_multi_value(struct osi_keyval_multi * kv, char* value) -{ - char* val_copy; - struct osi_value * value_container; - - if (!kv || !value) - return -EINVAL; - - val_copy = strdup(value); - value_container = malloc(sizeof(*value_container)); - if (!val_copy || !value_container) { - free(val_copy); - free(value_container); - return -ENOMEM; - } - - value_container->val = val_copy; - list_add_tail(&value_container->list, &kv->values_list); - kv->num_values += 1; - return 0; -} - -int __osi_store_keyval(char* key, char* value, struct list_head * list, int* num) -{ - struct osi_keyval_multi * kv; - - if (!key || !value || !list || !num) - return -EINVAL; - - kv = __osi_find_or_create_kv(key, list, num); - if (!kv) - return -ENOMEM; - - return __osi_add_keyval_multi_value(kv, value); -} - -void __osi_free_kv_pair(struct osi_keyval * kv_pair) -{ - if (!kv_pair) - return; - free(kv_pair->key); - free(kv_pair->value); - free(kv_pair); -} - -void __osi_free_device_section(struct osi_device_section * section) -{ - struct list_head * cursor, * tmp; - struct osi_device_link * dev_link; - - if (!section) - return; - list_for_each_safe(cursor, tmp, §ion->devices_list) { - dev_link = list_entry(cursor, struct osi_device_link, list); - list_del(cursor); - free(dev_link->driver); - free(dev_link->id); - free(dev_link); - } - free(section->type); - free(section); -} - -void __osi_free_hv(struct osi_internal_hv * hv) -{ - struct list_head * cursor, * tmp; - struct osi_device_section * section; - struct osi_keyval_multi * kv; - - if (!hv) - return; - - list_for_each_safe(cursor, tmp, &hv->param_list) { - kv = list_entry(cursor, struct osi_keyval_multi, list); - list_del(cursor); - __osi_free_keyval(kv); - } - - list_for_each_safe(cursor, tmp, &hv->dev_sections_list) { - section = list_entry(cursor, struct osi_device_section, list); - list_del(cursor); - __osi_free_device_section(section); - } - - free(hv->id); - free(hv); -} - -void __osi_free_device(struct osi_internal_dev * dev) -{ - struct list_head * cursor, * tmp; - struct osi_keyval_multi * kv; - - if (!dev) - return; - - list_for_each_safe(cursor, tmp, &dev->param_list) { - kv = list_entry(cursor, struct osi_keyval_multi, list); - list_del(&kv->list); - __osi_free_keyval(kv); - } - free(dev->id); - free(dev); -} - -void __osi_free_hypervisor_link(struct osi_hypervisor_link * hv_link) -{ - struct list_head * cursor, * tmp; - struct osi_device_section * section; - - if (!hv_link) - return; - - list_for_each_safe(cursor, tmp, &hv_link->dev_sections_list) { - section = list_entry(cursor, struct osi_device_section, list); - list_del(cursor); - __osi_free_device_section(section); - } - free(hv_link->hv_id); - free(hv_link); -} - -void __osi_free_os(struct osi_internal_os * os) -{ - struct list_head * cursor, * tmp; - struct osi_device_section * section; - struct osi_keyval_multi * kv; - struct osi_hypervisor_link * hv_link; - struct osi_os_link * os_link; - - if (!os) - return; - - list_for_each_safe(cursor, tmp, &os->param_list) { - kv = list_entry(cursor, struct osi_keyval_multi, list); - list_del(&kv->list); - __osi_free_keyval(kv); - } - - list_for_each_safe(cursor, tmp, &os->hypervisor_info_list) { - hv_link = list_entry(cursor, struct osi_hypervisor_link, list); - list_del(cursor); - __osi_free_hypervisor_link(hv_link); - } - - list_for_each_safe(cursor, tmp, &os->dev_sections_list) { - section = list_entry(cursor, struct osi_device_section, list); - list_del(cursor); - __osi_free_device_section(section); - } - - list_for_each_safe(cursor, tmp, &os->relationships_list) { - os_link = list_entry(cursor, struct osi_os_link, list); - list_del(cursor); - __osi_free_os_link(os_link); - } - - free(os->id); - free(os); -} - -void __osi_free_lib(struct osi_internal_lib * lib) -{ - struct list_head * cursor, * tmp; - struct osi_keyval * kv_pair; - struct osi_internal_hv * hv; - struct osi_internal_dev * dev; - struct osi_internal_os * os; - - if (!lib) - return; - - list_for_each_safe(cursor, tmp, &lib->param_list) { - kv_pair = list_entry(cursor, struct osi_keyval, list); - list_del(&kv_pair->list); - __osi_free_kv_pair(kv_pair); - } - - list_for_each_safe(cursor, tmp, &lib->hypervisor_list) { - hv = list_entry(cursor, struct osi_internal_hv, list); - list_del(&hv->list); - __osi_free_hv(hv); - } - /* Don't free lib->lib_hypervisor since we've already freed all of them */ - - list_for_each_safe(cursor, tmp, &lib->device_list) { - dev = list_entry(cursor, struct osi_internal_dev, list); - list_del(&dev->list); - __osi_free_device(dev); - } - - list_for_each_safe(cursor, tmp, &lib->os_list) { - os = list_entry(cursor, struct osi_internal_os, list); - list_del(&os->list); - __osi_free_os(os); - } - - free(lib->libvirt_version); - free(lib->backing_data_location); - free(lib); -} - -void __osi_cleanup_hv_link(struct osi_hypervisor_link * hv_link) -{ - struct list_head * cursor, * tmp; - struct osi_device_section * section; - - list_for_each_safe(cursor, tmp, &hv_link->dev_sections_list) { - section = list_entry(cursor, struct osi_device_section, list); - list_del(cursor); - __osi_free_device_section(section); - } - free(hv_link->hv_id); - free(hv_link); -} - -struct osi_internal_dev * __osi_find_dev_by_id(struct osi_internal_lib * lib, - char* id) -{ - struct list_head * cursor; - struct osi_internal_dev * dev = NULL, * test_dev; - - if (!lib) - return NULL; - - list_for_each(cursor, &lib->device_list) { - test_dev = list_entry(cursor, struct osi_internal_dev, list); - if (strcmp(id, test_dev->id) == 0) { - dev = test_dev; - break; - } - } - - return dev; -} - -struct osi_internal_hv * __osi_find_hv_by_id(struct osi_internal_lib * lib, - char* id) -{ - struct list_head * cursor; - struct osi_internal_hv * hv = NULL, * test_hv; - - if (!lib) - return NULL; - - list_for_each(cursor, &lib->hypervisor_list) { - test_hv = list_entry(cursor, struct osi_internal_hv, list); - if (strcmp(id, test_hv->id) == 0) { - hv = test_hv; - break; - } - } - - return hv; -} - -struct osi_internal_os * __osi_find_os_by_id(struct osi_internal_lib * lib, - char* id) -{ - struct list_head * cursor; - struct osi_internal_os * os = NULL, * test_os; - - if (!lib) - return NULL; - - list_for_each(cursor, &lib->os_list) { - test_os = list_entry(cursor, struct osi_internal_os, list); - if (strcmp(id, test_os->id) == 0) { - os = test_os; - break; - } - } - - return os; -} - -void __osi_free_os_link(struct osi_os_link * os_link) -{ - if (!os_link) - return; - - free(os_link->dobj_os_id); - free(os_link); -} - -void __osi_free_filter_relationship(struct osi_filter_relationship * fr) -{ - free(fr); -} diff --git a/src/osi_device.c b/src/osi_device.c deleted file mode 100644 index 8936fdb..0000000 --- a/src/osi_device.c +++ /dev/null @@ -1,675 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <libosinfo.h> -#include "list.h" -#include "osi_internal_types.h" - -static struct list_head * get_device_section_list(struct osi_internal_os * os) -{ - struct osi_hypervisor_link * hv_link; - - /* Check if hypervisor is set and if os has specific rules for the hv */ - if (os->lib->lib_hypervisor) - list_for_each_entry(hv_link, &os->hypervisor_info_list, list) { - if (hv_link->hv == os->lib->lib_hypervisor) - return &hv_link->dev_sections_list; - } - - /* Either no hv set for lib, or specific rules for hv not found for os */ - return &os->dev_sections_list; -} - -static char** dev_property_all_values(struct osi_internal_dev * dev, - char* propname, - int* num, - int* err) -{ - int i; - char** property_values; - struct osi_keyval_multi *kv = NULL; - struct osi_keyval_multi *test_kv; - struct list_head * cursor; - struct osi_value * value; - - /* First find the appropriate node based on propname */ - list_for_each(cursor, &dev->param_list) { - test_kv = list_entry(cursor, struct osi_keyval_multi, list); - if (strcmp(propname, test_kv->key) == 0) { - kv = test_kv; - break; - } - } - if (!kv) { - *err = -EINVAL; - return NULL; - } - - /* Found it, now copy all the values over */ - property_values = malloc(sizeof(*property_values) * kv->num_values); - if (!property_values) { - *err = -ENOMEM; - return NULL; - } - - i = 0; - list_for_each_entry(value, &kv->values_list, list) { - if (i == kv->num_values) - goto error; /* should *never* happen */ - - property_values[i] = strdup(value->val); - if (!property_values[i]) - goto error; - i += 1; - } - - *err = 0; - *num = kv->num_values; - return property_values; - -error: - for (i -= 1; i >= 0; i--) - free(property_values[i]); - free(property_values); - *err = -ENOMEM; - return NULL; -} - -static osi_device_list_t wrapped_dev_list(struct osi_dev_list * dev_list) -{ - struct osi_generic_type * dev_list_container; - - dev_list_container = malloc(sizeof(*dev_list_container)); - if (!dev_list_container) { - return NULL; - } - - dev_list_container->backing_object = dev_list; - dev_list_container->initialized = 1; - dev_list_container->type = OSI_DEVICE_LIST_T; - dev_list_container->error = 0; - - return dev_list_container; -} - -static int dev_passes_filter(struct osi_internal_dev * dev, - struct osi_internal_filter * filter) -{ - struct osi_keyval * kv; - char** values; - int num, err, i, match; - - /* Any device passes the null filter */ - if (!filter) - return 1; - - /* Check if it passes all normal constraints */ - list_for_each_entry(kv, &filter->constraints_list, list) { - values = dev_property_all_values(dev, kv->key, &num, &err); - if (!values || err != 0) - return 0; - - /* Check to see if one of the values is a match */ - match = 0; - for (i = 0; i < num; i++) { - if (strcmp(values[i], kv->value) == 0) { - match = 1; - break; - } - } - /* Free values we got since we're done with them */ - for (i = 0; i < num; i++) - free(values[i]); - free(values); - - /* If no match then fail, else continue */ - if (!match) - return 0; - } - - /* And if it does, then it passes the filter */ - return 1; -} - -osi_device_list_t osi_hypervisor_devices(osi_hypervisor_t hv, char* type, osi_filter_t filter, int* err) -{ - int len; - struct osi_generic_type * dev_list_container; - struct osi_dev_list * dev_list; - struct osi_internal_dev ** dev_refs, * dev; - struct osi_internal_hv * internal_hv; - struct osi_internal_filter * internal_filter; - struct osi_device_section * dev_section = NULL, * test_dev_section; - struct osi_device_link * device_link; - struct list_head * cursor; - - if (!err) - return NULL; - - if (!osi_check_hv(hv) || - !type || - (filter!= NULL && !osi_check_filter(filter)) ) { - *err = -EINVAL; - return NULL; - } - - internal_hv = hv->backing_object; - - if (filter != NULL) - internal_filter = filter->backing_object; - else - internal_filter = NULL; - - len = 0; - - /* Find the device section */ - list_for_each(cursor, &internal_hv->dev_sections_list) { - test_dev_section = list_entry(cursor, struct osi_device_section, list); - if (strcmp(test_dev_section->type, type) == 0) { - dev_section = test_dev_section; - break; - } - } - /* Could not find the section for the given device type */ - if (!dev_section) { - *err = -EINVAL; - return NULL; - } - - dev_list = malloc(sizeof(*dev_list)); - dev_refs = malloc(sizeof(*dev_refs) * dev_section->num_devices); - if (!dev_list || !dev_refs) { - free(dev_list); - free(dev_refs); - *err = -ENOMEM; - return NULL; - } - - /* Iterate dev list and check against filter (adding to list if passed) */ - list_for_each_entry(device_link, &dev_section->devices_list, list) { - dev = device_link->dev; - if (dev_passes_filter(dev, internal_filter)) { - dev_refs[len] = dev; - len += 1; - } - } - - /* Resize the list so we're not wasting memory */ - dev_refs = realloc(dev_refs, sizeof(*dev_refs) * len); - if (!dev_refs) { - free(dev_list); - *err = -ENOMEM; - return NULL; - } - - dev_list->dev_refs = dev_refs; - dev_list->length = len; - dev_list_container = wrapped_dev_list(dev_list); - if (!dev_list_container) { - free(dev_list); - free(dev_refs); - *err = -ENOMEM; - return NULL; - } - - *err = 0; - return dev_list_container; -} - -osi_device_list_t osi_os_devices(osi_os_t os, char* type, osi_filter_t filter, int* err) -{ - int len; - struct osi_generic_type * dev_list_container; - struct osi_dev_list * dev_list; - struct osi_internal_dev ** dev_refs, * dev; - struct osi_internal_os * internal_os; - struct osi_internal_filter * internal_filter; - struct osi_device_section * dev_section = NULL, * test_dev_section; - struct osi_device_link * device_link; - struct list_head * cursor, * dev_sections_list = NULL; - - if (!err) - return NULL; - - if (!osi_check_os(os) || - !type || - (filter!= NULL && !osi_check_filter(filter)) ) { - *err = -EINVAL; - return NULL; - } - - internal_os = os->backing_object; - - if (filter != NULL) - internal_filter = filter->backing_object; - else - internal_filter = NULL; - - len = 0; - - /* Ensure we check best possible data list for <os, hv> */ - dev_sections_list = get_device_section_list(internal_os); - - /* Find the device section */ - list_for_each(cursor, dev_sections_list) { - test_dev_section = list_entry(cursor, struct osi_device_section, list); - if (strcmp(test_dev_section->type, type) == 0) { - dev_section = test_dev_section; - break; - } - } - /* Could not find the section for the given device type */ - if (!dev_section) { - *err = -EINVAL; - return NULL; - } - - dev_list = malloc(sizeof(*dev_list)); - dev_refs = malloc(sizeof(*dev_refs) * dev_section->num_devices); - if (!dev_list || !dev_refs) { - free(dev_list); - free(dev_refs); - *err = -ENOMEM; - return NULL; - } - - /* Iterate dev list and check against filter (adding to list if passed) */ - list_for_each_entry(device_link, &dev_section->devices_list, list) { - dev = device_link->dev; - if (dev_passes_filter(dev, internal_filter)) { - dev_refs[len] = dev; - len += 1; - } - } - - /* Resize the list so we're not wasting memory */ - dev_refs = realloc(dev_refs, sizeof(*dev_refs) * len); - if (!dev_refs) { - free(dev_list); - *err = -ENOMEM; - return NULL; - } - - dev_list->dev_refs = dev_refs; - dev_list->length = len; - dev_list_container = wrapped_dev_list(dev_list); - if (!dev_list_container) { - free(dev_list); - free(dev_refs); - *err = -ENOMEM; - return NULL; - } - - *err = 0; - return dev_list_container; -} - -int osi_free_devices_list(osi_device_list_t list) -{ - struct osi_dev_list * dev_list; - - if (!osi_check_dev_list(list)) - return -EINVAL; - - dev_list = list->backing_object; - - free(dev_list->dev_refs); - free(dev_list); - free(list); - return 0; -} - -int osi_devices_list_length(osi_device_list_t list) -{ - struct osi_dev_list * dev_list; - - if (!osi_check_dev_list(list)) - return -EINVAL; - - dev_list = list->backing_object; - return dev_list->length; -} - -static osi_device_t wrapped_dev(struct osi_internal_dev * dev, int* err) -{ - struct osi_generic_type * dev_container; - - dev_container = malloc(sizeof(*dev_container)); - if (!dev_container) { - *err = -ENOMEM; - return NULL; - } - - dev_container->backing_object = dev; - dev_container->initialized = 1; - dev_container->type = OSI_DEVICE_T; - dev_container->error = 0; - - *err = 0; - return dev_container; -} - -osi_device_t osi_get_device_by_index(osi_device_list_t list, int idx, int* err) -{ - struct osi_dev_list * dev_list; - struct osi_internal_dev * dev; - - if (!err) - return NULL; - - if (!osi_check_dev_list(list)) { - *err = -EINVAL; - return NULL; - } - - dev_list = list->backing_object; - - /* Check bounds */ - if (idx < 0 || idx >= dev_list->length) { - *err = -EINVAL; - return NULL; - } - - dev = dev_list->dev_refs[idx]; - return wrapped_dev(dev, err); -} - -osi_device_t osi_get_preferred_device(osi_os_t os, char* type, osi_filter_t filter, int* err) -{ - struct osi_internal_dev * dev = NULL, * test_dev; - struct osi_internal_os * internal_os; - struct osi_internal_filter * internal_filter; - struct osi_device_section * dev_section = NULL, * test_dev_section; - struct osi_device_link * device_link; - struct list_head * cursor, * dev_sections_list; - - if (!err) - return NULL; - - if (!osi_check_os(os) || - !type || - (filter!= NULL && !osi_check_filter(filter)) ) { - *err = -EINVAL; - return NULL; - } - - internal_os = os->backing_object; - - if (filter != NULL) - internal_filter = filter->backing_object; - else - internal_filter = NULL; - - /* Ensure we check best possible data list for <os, hv> */ - dev_sections_list = get_device_section_list(internal_os); - - /* Find the device section */ - list_for_each(cursor, dev_sections_list) { - test_dev_section = list_entry(cursor, struct osi_device_section, list); - if (strcmp(test_dev_section->type, type) == 0) { - dev_section = test_dev_section; - break; - } - } - /* Could not find the section for the given device type */ - if (!dev_section) { - *err = -EINVAL; - return NULL; - } - - /* Iterate dev list and check against filter (adding to list if passed) */ - list_for_each_entry(device_link, &dev_section->devices_list, list) { - test_dev = device_link->dev; - if (dev_passes_filter(test_dev, internal_filter)) { - dev = test_dev; - break; - } - } - - if (!dev) { - *err = -EINVAL; - return NULL; - } - - return wrapped_dev(dev, err); -} - -char* osi_get_device_driver(osi_device_t dev, char* type, osi_os_t os, int* err) -{ - /* Search class, for the given hv, for the device */ - /* If not found, return NULL (no driver) for given class */ - /* Else return driver */ - - char* driver; - struct osi_internal_dev * internal_dev; - struct osi_internal_os * internal_os; - struct osi_device_section * dev_section = NULL, * test_dev_section; - struct osi_device_link * device_link = NULL, *test_device_link; - struct list_head * cursor, * dev_sections_list; - - if (!err) - return NULL; - - if (!osi_check_os(os) || !osi_check_dev(dev) || !type) { - *err = -EINVAL; - return NULL; - } - - internal_os = os->backing_object; - internal_dev = dev->backing_object; - - /* Ensure we check best possible data list for <os, hv> */ - dev_sections_list = get_device_section_list(internal_os); - - /* Find the device section */ - list_for_each(cursor, dev_sections_list) { - test_dev_section = list_entry(cursor, struct osi_device_section, list); - if (strcmp(test_dev_section->type, type) == 0) { - dev_section = test_dev_section; - break; - } - } - /* Could not find the section for the given device type */ - if (!dev_section) { - *err = -EINVAL; - return NULL; - } - - /* Iterate dev list to find device link with driver */ - list_for_each_entry(test_device_link, &dev_section->devices_list, list) { - if (test_device_link->dev == internal_dev) { - device_link = test_device_link; - break; - } - } - if (!device_link) { - *err = -EINVAL; - return NULL; - } - - driver = strdup(device_link->driver); - if (!driver) { - *err = -ENOMEM; - return NULL; - } - - *err = 0; - return driver; -} - -char* osi_device_id(osi_device_t dev, int* err) -{ - struct osi_internal_dev * internal_dev; - char* id; - - if (!err) - return NULL; - - if (!osi_check_dev(dev)) { - *err = -EINVAL; - return NULL; - } - - internal_dev = dev->backing_object; - - id = strdup(internal_dev->id); - if (!id) { - *err = -ENOMEM; - return NULL; - } - - *err = 0; - return id; -} - -osi_device_t osi_get_device_by_id(osi_lib_t lib, char* device_id, int* err) -{ - struct osi_generic_type * dev_container; - struct osi_internal_dev * dev, * test_dev; - struct list_head * cursor; - struct osi_internal_lib * internal_lib; - - if (!err) - return NULL; - - if (!osi_check_lib(lib) || !device_id) { - *err = -EINVAL; - return NULL; - } - - internal_lib = lib->backing_object; - - dev = NULL; - list_for_each(cursor, &internal_lib->device_list) { - test_dev = list_entry(cursor, struct osi_internal_dev, list); - if (strcmp(device_id, test_dev->id) == 0) { - dev = test_dev; - break; - } - } - - /* Hypervisor not found */ - if (!dev) { - *err = -EINVAL; - return NULL; - } - - dev_container = malloc(sizeof(*dev_container)); - if (!dev_container) { - *err = -ENOMEM; - return NULL; - } - - dev_container->backing_object = dev; - dev_container->type = OSI_DEVICE_T; - dev_container->error = 0; - dev_container->initialized = 1; - - *err = 0; - return dev_container; -} - -char** osi_get_all_device_property_keys(osi_device_t dev, int* num, int* err) -{ - int i; - char** property_keys; - struct osi_internal_dev * internal_dev; - struct osi_keyval_multi * kv; - - if (!err) - return NULL; - - if (!osi_check_dev(dev) || !num) { - *err = -EINVAL; - return NULL; - } - - internal_dev = dev->backing_object; - property_keys = malloc(sizeof(*property_keys) * internal_dev->num_params); - if (!property_keys) { - *err = -ENOMEM; - return NULL; - } - - i = 0; - list_for_each_entry(kv, &internal_dev->param_list, list) { - if (i == internal_dev->num_params) - goto error; /* Should *never* happen */ - - property_keys[i] = strdup(kv->key); - if (!property_keys[i]) - goto error; - i += 1; - } - - *err = 0; - *num = internal_dev->num_params; - return property_keys; - -error: - for (i -= 1; i > 0; i--) - free(property_keys[i]); - free(property_keys); - *err = -ENOMEM; - return NULL; -} - -char** osi_get_device_property_all_values(osi_device_t dev, char* propname, int* num, int* err) -{ - struct osi_internal_dev * internal_dev; - - if (!err) - return NULL; - - if (!osi_check_dev(dev) || !propname || !num) { - *err = -EINVAL; - return NULL; - } - - internal_dev = dev->backing_object; - return dev_property_all_values(internal_dev, propname, num, err); -} - -char* osi_get_device_property_value(osi_device_t dev, char* propname, int* err) -{ - char* value; - struct osi_internal_dev * internal_dev; - struct osi_keyval_multi *kv = NULL; - struct osi_keyval_multi *test_kv; - struct list_head * cursor; - struct osi_value * value_container; - - if (!err) - return NULL; - - if (!osi_check_dev(dev) || !propname) { - *err = -EINVAL; - return NULL; - } - - internal_dev = dev->backing_object; - - /* First find the appropriate node based on propname */ - list_for_each(cursor, &internal_dev->param_list) { - test_kv = list_entry(cursor, struct osi_keyval_multi, list); - if (strcmp(propname, test_kv->key) == 0) { - kv = test_kv; - break; - } - } - if (!kv) { - *err = -EINVAL; - return NULL; - } - - /* Found it, and there is at least one value set */ - cursor = kv->values_list.next; - value_container = list_entry(cursor, struct osi_value, list); - value = strdup(value_container->val); - if (!value) { - *err = -ENOMEM; - return NULL; - } - return value; -} diff --git a/src/osi_filter.c b/src/osi_filter.c deleted file mode 100644 index 5fa10ee..0000000 --- a/src/osi_filter.c +++ /dev/null @@ -1,358 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <libosinfo.h> -#include "list.h" -#include "osi_internal_types.h" - -osi_filter_t osi_get_filter(osi_lib_t lib, int* err) -{ - struct osi_generic_type * filter_container; - struct osi_internal_filter * filter; - struct osi_internal_lib * internal_lib; - - if (!osi_check_lib(lib) || !lib->initialized) { - *err = -EINVAL; - return NULL; - } - - internal_lib = lib->backing_object; - - filter = malloc(sizeof(*filter)); - filter_container = malloc(sizeof(*filter_container)); - if (!filter || !filter_container) { - free(filter); - free(filter_container); - *err = -ENOMEM; - return NULL; - } - - filter->num_constraints = 0; - INIT_LIST_HEAD(&filter->constraints_list); - filter->num_relationship_constraints = 0; - INIT_LIST_HEAD(&filter->relationship_constraints_list); - filter->lib = internal_lib; - - filter_container->backing_object = filter; - filter_container->type = OSI_FILTER_T; - filter_container->error = 0; - filter_container->initialized = 1; - - *err = 0; - return filter_container; -} - -static void clear_constraints(struct osi_internal_filter * filter) -{ - struct osi_filter_relationship * filter_relationship; - struct osi_keyval * kv_pair; - struct list_head * cursor, * tmp; - - list_for_each_safe(cursor, tmp, &filter->constraints_list) { - kv_pair = list_entry(cursor, struct osi_keyval, list); - list_del(&kv_pair->list); - __osi_free_kv_pair(kv_pair); - } - filter->num_constraints = 0; - - list_for_each_safe(cursor, tmp, &filter->relationship_constraints_list) { - filter_relationship = list_entry(cursor, struct osi_filter_relationship, list); - list_del(&filter_relationship->list); - __osi_free_filter_relationship(filter_relationship); - } - filter->num_relationship_constraints = 0; -} - -int osi_free_filter(osi_filter_t filter) -{ - struct osi_internal_filter * internal_filter; - - if (!osi_check_filter(filter)) - return -EINVAL; - - internal_filter = filter->backing_object; - clear_constraints(internal_filter); - - free(internal_filter); - free(filter); - return 0; -} - -int osi_add_filter_constraint(osi_filter_t filter, char* propname, char* propval) -{ - struct osi_keyval * kv_pair = NULL, * test_kv_pair; - struct osi_internal_filter * internal_filter; - char * key_copy, * val_copy; - struct list_head * cursor; - - if (!osi_check_filter(filter) || !propname || !propval) - return -EINVAL; - - if (strlen(propname) == 0 || strlen(propval) == 0) - return -EINVAL; - - /* Will definitely need to copy the value */ - val_copy = strdup(propval); - if (!val_copy) - return -ENOMEM; - - /* Check if some value is already set for given key so we can reuse slot */ - internal_filter = filter->backing_object; - list_for_each(cursor, &internal_filter->constraints_list) { - test_kv_pair = list_entry(cursor, struct osi_keyval, list); - if (strcmp(test_kv_pair->key, propname) == 0) { - kv_pair = test_kv_pair; - break; - } - } - - if (!kv_pair) { /* Need to make new slot for <key, val> */ - kv_pair = malloc(sizeof(*kv_pair)); - key_copy = strdup(propname); - if (!kv_pair || !key_copy) { - free(kv_pair); - free(key_copy); - free(val_copy); - return -ENOMEM; - } - kv_pair->key = key_copy; - internal_filter->num_constraints += 1; - list_add_tail(&kv_pair->list, &internal_filter->constraints_list); - } - else /* Need to free existing value before replacing with new */ - free(kv_pair->value); - - kv_pair->value = val_copy; - return 0; -} - -int osi_add_relation_constraint(osi_filter_t filter, osi_relationship relationship, osi_os_t os) -{ - struct osi_filter_relationship * filter_relationship = NULL, * test_fr; - struct osi_internal_filter * internal_filter; - struct osi_internal_os * internal_os; - struct list_head * cursor; - - if (!osi_check_filter(filter) || !osi_check_os(os)) - return -EINVAL; - - internal_filter = filter->backing_object; - internal_os = os->backing_object; - - list_for_each(cursor, &internal_filter->relationship_constraints_list) { - test_fr = list_entry(cursor, struct osi_filter_relationship, list); - if (test_fr->relationship == relationship) { - filter_relationship = test_fr; - break; - } - } - - if (!filter_relationship) { - filter_relationship = malloc(sizeof(*filter_relationship)); - if (!filter_relationship) - return -ENOMEM; - list_add_tail(&filter_relationship->list, &internal_filter->relationship_constraints_list); - internal_filter->num_relationship_constraints += 1; - } - - filter_relationship->os = internal_os; - filter_relationship->relationship = relationship; - return 0; -} - -int osi_clear_filter_constraint(osi_filter_t filter, char* propname) -{ - struct osi_keyval * kv_pair = NULL, * test_kv_pair; - struct osi_internal_filter * internal_filter; - struct list_head * cursor; - - if (!osi_check_filter(filter) || !propname) - return -EINVAL; - - /* Search for slot containing given key */ - internal_filter = filter->backing_object; - list_for_each(cursor, &internal_filter->constraints_list) { - test_kv_pair = list_entry(cursor, struct osi_keyval, list); - if (strcmp(test_kv_pair->key, propname) == 0) { - kv_pair = test_kv_pair; - break; - } - } - - /* Didn't find it, so we're done */ - if (!kv_pair) - return -EINVAL; - - /* Found it, so delete it */ - list_del(&kv_pair->list); - internal_filter->num_constraints -= 1; - __osi_free_kv_pair(kv_pair); - return 0; -} - -int osi_clear_relation_constraint(osi_filter_t filter, osi_relationship relationship) -{ - struct osi_filter_relationship * filter_relationship = NULL, * test_fr; - struct osi_internal_filter * internal_filter; - struct list_head * cursor; - - if (!osi_check_filter(filter)) - return -EINVAL; - - internal_filter = filter->backing_object; - - list_for_each(cursor, &internal_filter->relationship_constraints_list) { - test_fr = list_entry(cursor, struct osi_filter_relationship, list); - if (test_fr->relationship == relationship) { - filter_relationship = test_fr; - break; - } - } - - if (!filter_relationship) - return 0; - - list_del(&filter_relationship->list); - internal_filter->num_relationship_constraints -= 1; - __osi_free_filter_relationship(filter_relationship); - return 0; -} - -int osi_clear_all_constraints(osi_filter_t filter) -{ - if (!osi_check_filter(filter)) - return -EINVAL; - - clear_constraints(filter->backing_object); - return 0; -} - -char** osi_get_filter_constraint_keys(osi_filter_t filter, int* len, int* err) -{ - struct osi_internal_filter * internal_filter; - struct osi_keyval * kv_pair; - char** keys; - int i; - - if (!err) - return NULL; - - if (!osi_check_filter(filter) || !len) { - *err = -EINVAL; - return NULL; - } - - internal_filter = filter->backing_object; - keys = malloc(sizeof(*keys) * internal_filter->num_constraints); - if (!keys) { - *err = -ENOMEM; - return NULL; - } - - i = 0; - list_for_each_entry(kv_pair, &internal_filter->constraints_list, list) { - if (i == internal_filter->num_constraints) - goto error; /* Should *never* happen */ - - keys[i] = strdup(kv_pair->key); - if (!keys[i]) - goto error; - i += 1; - } - *err = 0; - *len = internal_filter->num_constraints; - return keys; - -error: - for (i -= 1; i >= 0; i--) - free(keys[i]); - free(keys); - *err = -ENOMEM; - return NULL; -} - -char* osi_get_filter_constraint_value(osi_filter_t filter, char* propname, int* err) -{ - struct osi_keyval * kv_pair = NULL, * test_kv_pair; - struct osi_internal_filter * internal_filter; - struct list_head * cursor; - char* val_copy; - - if (!err) - return NULL; - - if (!osi_check_filter(filter) || !propname) { - *err = -EINVAL; - return NULL; - } - - /* Search for slot containing given key */ - internal_filter = filter->backing_object; - list_for_each(cursor, &internal_filter->constraints_list) { - test_kv_pair = list_entry(cursor, struct osi_keyval, list); - if (strcmp(test_kv_pair->key, propname) == 0) { - kv_pair = test_kv_pair; - break; - } - } - - /* Didn't find it, so we're done */ - if (!kv_pair) { - *err = 0; - return NULL; - } - - /* Found it; duplicate value and return */ - val_copy = strdup(kv_pair->value); - if (!val_copy) - *err = -ENOMEM; - else - *err = 0; - return val_copy; -} - -osi_os_t osi_get_relationship_constraint_value(osi_filter_t filter, osi_relationship relationship, int* err) -{ - struct osi_generic_type * os_container; - struct osi_filter_relationship * filter_relationship = NULL, * test_fr; - struct osi_internal_filter * internal_filter; - struct list_head * cursor; - - if (!err) - return NULL; - - if (!osi_check_filter(filter)) { - *err = -EINVAL; - return NULL; - } - - internal_filter = filter->backing_object; - - list_for_each(cursor, &internal_filter->relationship_constraints_list) { - test_fr = list_entry(cursor, struct osi_filter_relationship, list); - if (test_fr->relationship == relationship) { - filter_relationship = test_fr; - break; - } - } - - if (!filter_relationship) { - *err = 0; - return NULL; - } - - os_container = malloc(sizeof(*os_container)); - if (!os_container) { - *err = -ENOMEM; - return NULL; - } - - os_container->backing_object = filter_relationship->os; - os_container->type = OSI_OS_T; - os_container->error = 0; - os_container->initialized = 1; - - *err = 0; - return os_container; -} diff --git a/src/osi_hv.c b/src/osi_hv.c deleted file mode 100644 index 9b233a4..0000000 --- a/src/osi_hv.c +++ /dev/null @@ -1,396 +0,0 @@ -#include <libosinfo.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include "list.h" -#include "osi_internal_types.h" - -char** osi_get_all_hypervisor_ids(osi_lib_t lib, int* num, int* err) -{ - int i; - char** ids; - struct osi_internal_hv * hv; - struct osi_internal_lib * internal_lib; - - if (!err) - return NULL; - - if (!osi_check_lib(lib) || !num) { - *err = -EINVAL; - return NULL; - } - - internal_lib = lib->backing_object; - - ids = malloc(sizeof(*ids) * internal_lib->num_hypervisors); - if (!ids) { - *err = -ENOMEM; - return NULL; - } - - i = 0; - list_for_each_entry(hv, &internal_lib->hypervisor_list, list) { - if (i == internal_lib->num_hypervisors) - goto error; /* This should *never* happen */ - ids[i] = strdup(hv->id); - if (!ids[i]) - goto error; - i += 1; - } - - *err = 0; - *num = internal_lib->num_hypervisors; - return ids; - -error: - for (i -= 1; i >= 0; i--) { - free(ids[i-1]); - } - free(ids); - *err = -ENOMEM; - return NULL; -} - -osi_hypervisor_t osi_get_hypervisor_by_id(osi_lib_t lib, char* hypervisor_id, int* err) -{ - struct osi_generic_type * hv_container; - struct osi_internal_hv * hv, * test_hv; - struct list_head * cursor; - struct osi_internal_lib * internal_lib; - - if (!err) - return NULL; - - if (!osi_check_lib(lib) || !hypervisor_id) { - *err = -EINVAL; - return NULL; - } - - internal_lib = lib->backing_object; - - hv = NULL; - list_for_each(cursor, &internal_lib->hypervisor_list) { - test_hv = list_entry(cursor, struct osi_internal_hv, list); - if (strcmp(hypervisor_id, test_hv->id) == 0) { - hv = test_hv; - break; - } - } - - /* Hypervisor not found */ - if (!hv) { - *err = -EINVAL; - return NULL; - } - - hv_container = malloc(sizeof(*hv_container)); - if (!hv_container) { - *err = -ENOMEM; - return NULL; - } - - hv_container->backing_object = hv; - hv_container->type = OSI_HYPERVISOR_T; - hv_container->error = 0; - hv_container->initialized = 1; - - *err = 0; - return hv_container; -} - -char* osi_get_hv_id(osi_hypervisor_t hv, int* err) -{ - struct osi_internal_hv * internal_hv; - char* id; - - if (!err) - return NULL; - - if (!osi_check_hv(hv)) { - *err = -EINVAL; - return NULL; - } - - internal_hv = hv->backing_object; - - id = strdup(internal_hv->id); - if (!id) { - *err = -ENOMEM; - return NULL; - } - - *err = 0; - return id; -} - -int osi_set_lib_hypervisor(osi_lib_t lib, char* hypervisor_id) -{ - struct osi_internal_hv * hv, * test_hv; - struct list_head * cursor; - struct osi_internal_lib * internal_lib; - - if (!osi_check_lib(lib)) - return -EINVAL; - - if (lib->initialized) - return -EBUSY; - - internal_lib = lib->backing_object; - - /* If hv id is NULL, unset any existing hv so lib uses 'default' hv */ - if (!hypervisor_id) { - internal_lib->lib_hypervisor = NULL; - return 0; - } - - /* Otherwise find hypervisor and set accordingly, or error if not found */ - hv = NULL; - list_for_each(cursor, &internal_lib->hypervisor_list) { - test_hv = list_entry(cursor, struct osi_internal_hv, list); - if (strcmp(hypervisor_id, test_hv->id) == 0) { - hv = test_hv; - break; - } - } - - if (!hv) - return -EINVAL; - - internal_lib->lib_hypervisor = hv; - return 0; -} - -osi_hypervisor_t osi_get_lib_hypervisor(osi_lib_t lib, int* err) -{ - struct osi_generic_type * hv_container; - struct osi_internal_lib * internal_lib; - - if (!err) - return NULL; - - if (!osi_check_lib(lib)) { - *err = -EINVAL; - return NULL; - } - - internal_lib = lib->backing_object; - - if (!internal_lib->lib_hypervisor) { - *err = 0; - return NULL; - } - - hv_container = malloc(sizeof(*hv_container)); - if (!hv_container) { - *err = -ENOMEM; - return NULL; - } - - hv_container->backing_object = internal_lib->lib_hypervisor; - hv_container->type = OSI_HYPERVISOR_T; - hv_container->error = 0; - hv_container->initialized = 1; - - *err = 0; - return hv_container; -} - -char** osi_get_hv_device_types(osi_hypervisor_t hv, int* num, int* err) -{ - int i; - struct osi_internal_hv * internal_hv; - struct osi_device_section * dev_section; - char** device_types; - - if (!err) - return NULL; - - if (!osi_check_hv(hv) || !num) { - *err = -EINVAL; - return NULL; - } - - internal_hv = hv->backing_object; - device_types = malloc(sizeof(*device_types) * internal_hv->num_dev_sections); - if (!device_types) { - *err = -ENOMEM; - return NULL; - } - - i = 0; - list_for_each_entry(dev_section, &internal_hv->dev_sections_list, list) { - if (i == internal_hv->num_dev_sections) - goto error; /* Should *never* happen */ - - device_types[i] = strdup(dev_section->type); - if (!device_types[i]) - goto error; - i += 1; - } - - *err = 0; - *num = internal_hv->num_dev_sections; - - return device_types; - -error: - for (i -= 1; i >= 0; i--) - free(device_types[i]); - free(device_types); - *err = -ENOMEM; - return NULL; -} - - -char** osi_get_hv_all_property_keys(osi_hypervisor_t hv, int* num, int* err) -{ - int i; - char** property_keys; - struct osi_internal_hv * internal_hv; - struct osi_keyval_multi * kv; - - if (!err) - return NULL; - - if (!osi_check_hv(hv) || !num) { - *err = -EINVAL; - return NULL; - } - - internal_hv = hv->backing_object; - property_keys = malloc(sizeof(*property_keys) * internal_hv->num_params); - if (!property_keys) { - *err = -ENOMEM; - return NULL; - } - - i = 0; - list_for_each_entry(kv, &internal_hv->param_list, list) { - if (i == internal_hv->num_params) - goto error; /* Should *never* happen */ - - property_keys[i] = strdup(kv->key); - if (!property_keys[i]) - goto error; - i += 1; - } - - *err = 0; - *num = internal_hv->num_params; - return property_keys; - -error: - for (i -= 1; i >= 0; i--) - free(property_keys[i]); - free(property_keys); - *err = -ENOMEM; - return NULL; -} - -char** osi_get_hv_property_all_values(osi_hypervisor_t hv, char* propname, int* num, int* err) -{ - int i; - char** property_values; - struct osi_internal_hv * internal_hv; - struct osi_keyval_multi *kv = NULL; - struct osi_keyval_multi *test_kv; - struct list_head * cursor; - struct osi_value * value; - - if (!err) - return NULL; - - if (!osi_check_hv(hv) || !propname || !num) { - *err = -EINVAL; - return NULL; - } - - internal_hv = hv->backing_object; - - /* First find the appropriate node based on propname */ - list_for_each(cursor, &internal_hv->param_list) { - test_kv = list_entry(cursor, struct osi_keyval_multi, list); - if (strcmp(propname, test_kv->key) == 0) { - kv = test_kv; - break; - } - } - if (!kv) { - *err = -EINVAL; - return NULL; - } - - /* Found it, now copy all the values over */ - property_values = malloc(sizeof(*property_values) * kv->num_values); - if (!property_values) { - *err = -ENOMEM; - return NULL; - } - - i = 0; - list_for_each_entry(value, &kv->values_list, list) { - if (i == kv->num_values) - goto error; /* should *never* happen */ - - property_values[i] = strdup(value->val); - if (!property_values[i]) - goto error; - i += 1; - } - - *err = 0; - *num = kv->num_values; - return property_values; - -error: - for (i -= 1; i >= 0; i--) - free(property_values[i]); - free(property_values); - *err = -ENOMEM; - return NULL; -} - - -char* osi_get_hv_property_first_value(osi_hypervisor_t hv, char* propname, int* err) -{ - char* value; - struct osi_internal_hv * internal_hv; - struct osi_keyval_multi *kv = NULL; - struct osi_keyval_multi *test_kv; - struct list_head * cursor; - struct osi_value * value_container; - - if (!err) - return NULL; - - if (!osi_check_hv(hv) || !propname) { - *err = -EINVAL; - return NULL; - } - - internal_hv = hv->backing_object; - - /* First find the appropriate node based on propname */ - list_for_each(cursor, &internal_hv->param_list) { - test_kv = list_entry(cursor, struct osi_keyval_multi, list); - if (strcmp(propname, test_kv->key) == 0) { - kv = test_kv; - break; - } - } - if (!kv) { - *err = -EINVAL; - return NULL; - } - - /* Found it, and there is at least one value set */ - cursor = kv->values_list.next; - value_container = list_entry(cursor, struct osi_value, list); - value = strdup(value_container->val); - if (!value) { - *err = -ENOMEM; - return NULL; - } - return value; -} diff --git a/src/osi_internal_types.h b/src/osi_internal_types.h deleted file mode 100644 index 8f74396..0000000 --- a/src/osi_internal_types.h +++ /dev/null @@ -1,181 +0,0 @@ -/* Forward Declarations */ -struct osi_internal_lib; - -enum OSI_LIB_STATE { - UNINITIALIZED, - INITIALIZED -}; - -struct osi_value { - char* val; - - struct list_head list; -}; - -struct osi_keyval_multi { - char* key; - int num_values; - struct list_head values_list; /* type is osi_value */ - - struct list_head list; -}; - -struct osi_keyval { - char* key; - char* value; - - struct list_head list; -}; - -struct osi_internal_dev { - char* id; - int num_params; - struct list_head param_list; /* type is osi_multi_keyval */ - - struct list_head list; - - struct osi_internal_lib * lib; -}; - -struct osi_device_link { - struct osi_internal_dev * dev; - char* driver; - char* id; - - struct list_head list; -}; - -struct osi_device_section { - char* type; - - int num_devices; - struct list_head devices_list; /* type is osi_device_link */ - - struct list_head list; -}; - -struct osi_internal_hv { - char* id; - - int num_params; - struct list_head param_list; /* type is osi_keyval_multi */ - - int num_dev_sections; - struct list_head dev_sections_list; /* type is osi_device_section */ - - struct list_head list; - - struct osi_internal_lib * lib; -}; - -struct osi_os_link { - /* <subject_os> 'verbs' <direct_object_os> - * fedora11 upgrades fedora10 - * centos clones rhel - * scientificlinux derives from rhel - */ - struct osi_internal_os * subject_os; - osi_relationship verb; - struct osi_internal_os * direct_object_os; - - char* dobj_os_id; - struct list_head list; -}; - -struct osi_internal_os { - char* id; - int num_params; - struct list_head param_list; /* type is osi_keyval */ - - /* Per Hypervisor info for this OS */ - int num_hypervisors; - struct list_head hypervisor_info_list; /* type is osi_hypervisor_link */ - - /* Information for usage with unspecified hypervisor */ - int num_dev_sections; - struct list_head dev_sections_list; /* type is osi_device_section */ - - int num_relationships; - struct list_head relationships_list; /* type is osi_os_link */ - - struct list_head list; - - struct osi_internal_lib * lib; -}; - -struct osi_filter_relationship { - struct osi_internal_os * os; - osi_relationship relationship; - - struct list_head list; -}; - -struct osi_hypervisor_link { - struct osi_internal_hv * hv; - struct osi_internal_os * os; - - char* hv_id; - - int num_dev_sections; - struct list_head dev_sections_list; /* type is osi_device_section */ - - struct list_head list; -}; - -struct osi_internal_lib { - enum OSI_LIB_STATE lib_state; - char* libvirt_version; - char* backing_data_location; - - int num_params; - struct list_head param_list; /* type is osi_keyval */ - - int num_hypervisors; - struct list_head hypervisor_list; /* type is osi_internal_hv */ - struct osi_internal_hv * lib_hypervisor; - - int num_devices; - struct list_head device_list; /* type is osi_internal_dev */ - - int num_os; - struct list_head os_list; /* type is osi_internal_os */ -}; - -struct osi_internal_filter { - int num_constraints; - struct list_head constraints_list; /* type is osi_keyval */ - - int num_relationship_constraints; - struct list_head relationship_constraints_list; /* type is osi_filter_relationship */ - - struct osi_internal_lib * lib; -}; - -struct osi_dev_list { - int length; - struct osi_internal_dev ** dev_refs; -}; - -struct osi_os_list { - int length; - struct osi_internal_os ** os_refs; -}; - -void __osi_free_keyval(struct osi_keyval_multi * kv); -void __osi_free_device_section(struct osi_device_section * section); -struct osi_keyval_multi * __osi_find_kv(char* key, struct list_head * search_list); -struct osi_keyval_multi * __osi_create_kv(char* key, struct list_head * dest_list); -struct osi_keyval_multi * __osi_find_or_create_kv(char* key, struct list_head * list, int* num); -int __osi_add_keyval_multi_value(struct osi_keyval_multi * kv, char* value); -int __osi_store_keyval(char* key, char* value, struct list_head * list, int* num); -void __osi_free_hv(struct osi_internal_hv * hv); -void __osi_free_device(struct osi_internal_dev * dev); -void __osi_free_os(struct osi_internal_os * os); -void __osi_free_kv_pair(struct osi_keyval * kv_pair); -void __osi_free_lib(struct osi_internal_lib * lib); -void __osi_free_hypervisor_link(struct osi_hypervisor_link * hv_link); -struct osi_internal_dev * __osi_find_dev_by_id(struct osi_internal_lib * lib, char* id); -struct osi_internal_hv * __osi_find_hv_by_id(struct osi_internal_lib * lib, char* id); -void __osi_free_os_link(struct osi_os_link * os_link); -struct osi_internal_os * __osi_find_os_by_id(struct osi_internal_lib * lib, char* id); -void __osi_free_filter_relationship(struct osi_filter_relationship * fr); diff --git a/src/osi_lib.c b/src/osi_lib.c deleted file mode 100644 index 9c53222..0000000 --- a/src/osi_lib.c +++ /dev/null @@ -1,328 +0,0 @@ -#include <libosinfo.h> -#include <stddef.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include "list.h" -#include "osi_internal_types.h" - -osi_lib_t osi_get_lib_handle(int* err, char* data_dir) -{ - int ret; - struct osi_generic_type * external_lib; - struct osi_internal_lib * internal_lib; - - /* If err is NULL, return NULL but we can't return the error... */ - if (!err) - return NULL; - - /* Allocate structures */ - external_lib = malloc(sizeof(*external_lib)); - internal_lib = malloc(sizeof(*internal_lib)); - data_dir = strdup(data_dir); - if (!external_lib || !internal_lib || !data_dir) { - *err = -ENOMEM; - free(external_lib); - free(internal_lib); - free(data_dir); - return NULL; - } - - /* Initial setup of structures */ - internal_lib->lib_state = UNINITIALIZED; - internal_lib->libvirt_version = NULL; - internal_lib->backing_data_location = data_dir; - internal_lib->lib_hypervisor = NULL; - - INIT_LIST_HEAD(&internal_lib->param_list); - internal_lib->num_params = 0; - - INIT_LIST_HEAD(&internal_lib->hypervisor_list); - internal_lib->num_hypervisors = 0; - - INIT_LIST_HEAD(&internal_lib->device_list); - internal_lib->num_devices = 0; - - INIT_LIST_HEAD(&internal_lib->os_list); - internal_lib->num_os = 0; - - external_lib->backing_object = internal_lib; - external_lib->initialized = 0; - external_lib->type = OSI_LIB_T; - external_lib->error = 0; - - /* Read in the backing data */ - ret = osi_initialize_data(internal_lib, data_dir); - if (ret != 0) { - *err = ret; - free(external_lib); - /* Don't free internal lib since it was cleaned up for us on failure */ - return NULL; - } - - /* Success, return the handle */ - *err = 0; - return external_lib; -} - -int osi_init_lib(osi_lib_t lib) -{ - struct osi_internal_lib * internal_lib; - - if (!osi_check_lib(lib) || lib->initialized) - return -EINVAL; - - internal_lib = lib->backing_object; - internal_lib->lib_state = INITIALIZED; - lib->initialized = 1; - - return 0; -} - -int osi_close_lib(osi_lib_t lib) -{ - struct osi_generic_type * external_lib; - struct osi_internal_lib * internal_lib; - - if (!osi_check_lib(lib) || !lib->initialized) - return -EINVAL; - - external_lib = lib; - internal_lib = external_lib->backing_object; - - if (internal_lib->lib_state != INITIALIZED) - return -EINVAL; - - __osi_free_lib(internal_lib); - free(external_lib); - - return 0; -} - -int osi_set_lib_param(osi_lib_t lib, char* key, char* val) -{ - struct osi_internal_lib * internal_lib; - struct osi_keyval * pair, * test_pair; - char * key_copy, * val_copy; - struct list_head * cursor; - - if (!osi_check_lib(lib) || !key) - return -EINVAL; - - internal_lib = lib->backing_object; - if (lib->initialized || internal_lib->lib_state == INITIALIZED) - return -EBUSY; - - /* If val is null, then remove value for given key. Else, - * make copy of the value so we can set it for the given key. - */ - if (!val) - val_copy = NULL; - else { - val_copy = strdup(val); - if (!val_copy) - return -ENOMEM; - } - - /* Short circuit for libvirt version */ - if (strcmp(key, "libvirt-version") == 0) { - free(internal_lib->libvirt_version); - internal_lib->libvirt_version = val_copy; - return 0; - } - - /* Short circuit for backing data location */ - if (strcmp(key, "backing-data-location") == 0) { - free(internal_lib->backing_data_location); - internal_lib->backing_data_location = val_copy; - return 0; - } - - /* Find the existing node containing the property if it exists */ - pair = NULL; - list_for_each(cursor, &internal_lib->param_list) { - test_pair = list_entry(cursor, struct osi_keyval, list); - if (strcmp(key, test_pair->key) == 0) { - pair = test_pair; - break; - } - } - - /* If we were deleting the property, go ahead and remove the key/val pair */ - if (!val_copy) { - - if (!pair) /* Deleting value that was never there, so return success */ - return 0; - - /* Remove the pair */ - list_del(&pair->list); - free(pair->key); - free(pair->value); - free(pair); - - internal_lib->num_params -= 1; - - return 0; - } - - /* Else we are adding or updating the value for the property */ - - /* If we did not find an existing value, make room for the new one */ - if (!pair) { - pair = malloc(sizeof(*pair)); - key_copy = strdup(key); - - if (!key_copy || !pair) { - free(key_copy); - free(val_copy); - free(pair); - return -ENOMEM; - } - - pair->key = key_copy; - list_add(&pair->list, &internal_lib->param_list); - internal_lib->num_params += 1; - } - - /* Free the existing value and set the new one */ - free(pair->value); - pair->value = val_copy; - - return 0; -} - -char* osi_get_lib_param(osi_lib_t lib, char* key, int* err) -{ - struct osi_internal_lib * internal_lib; - struct osi_keyval * pair, * test_pair; - struct list_head * cursor; - char* value; - - if (!err) - return NULL; - - if (!osi_check_lib(lib) || !key) { - *err = -EINVAL; - return NULL; - } - - internal_lib = lib->backing_object; - - /* Short circuit for libvirt version */ - if (strcmp(key, "libvirt-version") == 0) { - if (!internal_lib->libvirt_version) { - *err = 0; - return NULL; - } - value = strdup(internal_lib->libvirt_version); - if (!value) { - *err = -ENOMEM; - return NULL; - } - *err = 0; - return value; - } - - /* Short circuit for backing data location */ - if (strcmp(key, "backing-data-location") == 0) { - if (!internal_lib->backing_data_location) { - *err = 0; - return NULL; - } - value = strdup(internal_lib->backing_data_location); - if (!value) { - *err = -ENOMEM; - return NULL; - } - *err = 0; - return value; - } - - /* Find the existing node containing the property if it exists */ - pair = NULL; - list_for_each(cursor, &internal_lib->param_list) { - test_pair = list_entry(cursor, struct osi_keyval, list); - if (strcmp(key, test_pair->key) == 0) { - pair = test_pair; - break; - } - } - - /* Value not found for given key */ - if (!pair) { - *err = 0; - return NULL; - } - - /* Duplicate value and return */ - value = strdup(pair->value); - if (!value) { - *err = -ENOMEM; - return NULL; - } - - *err = 0; - return value; -} - -int osi_is_error(osi_generic_t t) -{ - if (!t) - return -EINVAL; - return t->error; -} - -int osi_is_null(osi_generic_t t) -{ - return (t == NULL); -} - -int osi_cleanup_handle(osi_generic_t t) -{ - if (!t) - return -EINVAL; - free(t); - return 0; -} - -int osi_check_lib(osi_lib_t lib) -{ - return (lib && lib->type == OSI_LIB_T && lib->backing_object); -} - -int osi_check_os(osi_os_t os) -{ - return (os && os->type == OSI_OS_T && os->backing_object); -} - -int osi_check_hv(osi_hypervisor_t hv) -{ - return (hv && hv->type == OSI_HYPERVISOR_T && hv->backing_object); -} - -int osi_check_filter(osi_filter_t filter) -{ - return (filter && filter->type == OSI_FILTER_T && filter->backing_object); -} - -int osi_check_os_list(osi_os_list_t list) -{ - return (list && list->type == OSI_OS_LIST_T && list->backing_object); -} - -int osi_check_dev_list(osi_device_list_t list) -{ - return (list && list->type == OSI_DEVICE_LIST_T && list->backing_object); -} - -int osi_check_dev(osi_device_t dev) -{ - return (dev && dev->type == OSI_DEVICE_T && dev->backing_object); -} - -int osi_valid_os_relationship(osi_relationship relationship) -{ - return (relationship == DERIVES_FROM || - relationship == UPGRADES || - relationship == CLONES); -} diff --git a/src/osi_os.c b/src/osi_os.c deleted file mode 100644 index 21128e1..0000000 --- a/src/osi_os.c +++ /dev/null @@ -1,738 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <libosinfo.h> -#include "list.h" -#include "osi_internal_types.h" - -static char** os_property_all_values(struct osi_internal_os * os, - char* propname, - int* num, - int* err) -{ - int i; - char** property_values; - struct osi_keyval_multi *kv = NULL; - struct osi_keyval_multi *test_kv; - struct list_head * cursor; - struct osi_value * value; - - /* First find the appropriate node based on propname */ - list_for_each(cursor, &os->param_list) { - test_kv = list_entry(cursor, struct osi_keyval_multi, list); - if (strcmp(propname, test_kv->key) == 0) { - kv = test_kv; - break; - } - } - if (!kv) { - *err = -EINVAL; - return NULL; - } - - /* Found it, now copy all the values over */ - property_values = malloc(sizeof(*property_values) * kv->num_values); - if (!property_values) { - *err = -ENOMEM; - return NULL; - } - - i = 0; - list_for_each_entry(value, &kv->values_list, list) { - if (i == kv->num_values) - goto error; /* should *never* happen */ - - property_values[i] = strdup(value->val); - if (!property_values[i]) - goto error; - i += 1; - } - - *err = 0; - *num = kv->num_values; - return property_values; - -error: - for (i -= 1; i >= 0; i--) - free(property_values[i]); - free(property_values); - *err = -ENOMEM; - return NULL; -} - -int append_in_place(char** dest, int dest_curr_len, char** src, int src_len) -{ - int i; - for (i = 0; i < src_len; i++) { - dest[dest_curr_len + i] = strdup(src[i]); - if (!dest[dest_curr_len + i]) - return -ENOMEM; - } - return dest_curr_len + src_len; -} - -char** append(char*** arrays, int* lengths, int numarrays, - int* newlength, int* err) -{ - char** combined; - int total_len, i, j; - - total_len = 0; - for (i = 0; i < numarrays; i++) - total_len += lengths[i]; - - combined = malloc(sizeof(*combined) * total_len); - if (!combined) { - *err = -ENOMEM; - return NULL; - } - - j = 0; - for (i = 0; i < numarrays; i++) { - j = append_in_place(combined, j, arrays[i], lengths[i]); - if (j < 0) - goto error; - } - - *newlength = j; - return combined; - -error: - for (j -= 1; j >= 0; j--) - free(combined[j]); - free(combined); - *err = -ENOMEM; - return NULL; -} - -char** copy_array(char** arr, int len, int* err) -{ - int i; - char** dup; - - dup = malloc(sizeof(*dup) * len); - if (!dup) { - *err = -ENOMEM; - return NULL; - } - - for (i = 0; i < len; i++) { - dup[i] = strdup(arr[i]); - if (!dup[i]) - goto error; - } - - *err = 0; - return dup; - -error: - for (i -= 1; i >= 0; i--) - free(dup[i]); - free(dup); - return NULL; -} - -int strcmp_wrapper(const void * a, const void * b) -{ - return strcmp(*(char **)a, *(char **)b); -} - -char** remove_duplicates(char** arr, int len, int* newlen, int* err) -{ - int i, j; - char ** dup, ** pruned; - - dup = copy_array(arr, len, err); - if (!dup || *err != 0) { - return NULL; - } - - /* Make space for pruned array */ - pruned = malloc(sizeof(*pruned) * len); - if (!pruned) { - for (i = 0; i < len; i++) - free(dup[i]); - free(dup); - - *err = -ENOMEM; - return NULL; - } - - /* Sort and copy over non-duplicate elements */ - qsort(dup, len, sizeof(*dup), strcmp_wrapper); - - j = 0; - for (i = 0; i < len; i++) { - pruned[j] = strdup(dup[i]); - if (!pruned[j]) - goto error; - while(i <= len - 2 && strcmp(dup[i], dup[i+1]) == 0) - i += 1; - j += 1; - } - - /* Free the pre-pruned array since we are done with it */ - for (i = 0; i < len; i++) - free(dup[i]); - free(dup); - - /* Get rid of excess space */ - pruned = realloc(pruned, sizeof(*pruned)*j); - if (!pruned) { - *err = -ENOMEM; - return NULL; - } - - *newlen = j; - return pruned; - -error: - for (j -= 1; j >= 0; j--) - free(pruned[j]); - free(pruned); - return NULL; -} - -char** osi_unique_property_values(osi_lib_t lib, char* propname, int* num, int* err) -{ - int i, j, len; - char *** os_values, ** unpruned, ** pruned, ** retval = NULL; - int * list_lengths; - struct osi_internal_lib * internal_lib; - struct osi_internal_os * os; - - if (!err) - return NULL; - - if (!osi_check_lib(lib) || !propname || !num) { - *err = -EINVAL; - return NULL; - } - - internal_lib = lib->backing_object; - - os_values = malloc(sizeof(*os_values) * internal_lib->num_os); - list_lengths = malloc(sizeof(*list_lengths) * internal_lib->num_os); - if (!os_values || !list_lengths) { - free(os_values); - free(list_lengths); - *err = -ENOMEM; - return NULL; - } - - /* First, for each os, get all values for the given propname */ - i = 0; - list_for_each_entry(os, &internal_lib->os_list, list) { - os_values[i] = os_property_all_values(os, propname, &list_lengths[i], err); - if (!os_values[i] || *err != 0) - goto out; - i += 1; - } - - /* Then, append all these lists together */ - unpruned = append(os_values, list_lengths, internal_lib->num_os, &len, err); - if (!unpruned || *err != 0) - goto out; - - /* Then, remove duplicates from the list and return */ - pruned = remove_duplicates(unpruned, len, num, err); - - /* Done with 'unpruned' sorted list */ - for (j = 0; j < len; j++) - free(unpruned[j]); - free(unpruned); - - if (!pruned || *err != 0) - goto out; - - else - retval = pruned; - -out: - for (i -= 1; i >= 0; i--) { - for (j = 0; j < list_lengths[i]; j++) - free(os_values[i][j]); - free(os_values[i]); - } - free(os_values); - free(list_lengths); - return retval; -} - -static struct osi_internal_os * get_related_os(struct osi_internal_os * os, - osi_relationship relationship, - int* err) -{ - struct osi_os_link * os_link = NULL, * test_os_link; - struct list_head * cursor; - - list_for_each(cursor, &os->relationships_list) { - test_os_link = list_entry(cursor, struct osi_os_link, list); - if (test_os_link->verb == relationship) { - os_link = test_os_link; - break; - } - } - - if (!os_link) { - *err = -EINVAL; - return NULL; - } - - *err = 0; - return os_link->direct_object_os; -} - -static int os_passes_filter(struct osi_internal_os * os, - struct osi_internal_filter * filter) -{ - struct osi_keyval * kv; - struct osi_filter_relationship * fr; - struct osi_internal_os * target_os; - char** values; - int num, err, i, match; - - /* Any os passes the null filter */ - if (!filter) - return 1; - - /* Check if it passes all normal constraints */ - list_for_each_entry(kv, &filter->constraints_list, list) { - values = os_property_all_values(os, kv->key, &num, &err); - if (!values || err != 0) - return 0; - - /* Check to see if one of the values is a match */ - match = 0; - for (i = 0; i < num; i++) { - if (strcmp(values[i], kv->value) == 0) { - match = 1; - break; - } - } - /* Free values we got since we're done with them */ - for (i = 0; i < num; i++) - free(values[i]); - free(values); - - /* If no match then fail, else continue */ - if (!match) - return 0; - } - - /* Check if it passes all relationship constraints */ - list_for_each_entry(fr, &filter->relationship_constraints_list, list) { - target_os = get_related_os(os, fr->relationship, &err); - if (!target_os || err != 0) - return 0; - - if (target_os != fr->os) - return 0; - } - - /* And if it does, then it passes the filter */ - return 1; -} - -static int os_participates_in_relationship(struct osi_internal_os * os, - osi_relationship relationship) -{ - struct osi_os_link * os_link; - - list_for_each_entry(os_link, &os->relationships_list, list) - if (os_link->verb == relationship) - return 1; - - return 0; -} - -static osi_os_list_t wrapped_os_list(struct osi_os_list * os_list) -{ - struct osi_generic_type * os_list_container; - - os_list_container = malloc(sizeof(*os_list_container)); - if (!os_list_container) { - return NULL; - } - - os_list_container->backing_object = os_list; - os_list_container->initialized = 1; - os_list_container->type = OSI_OS_LIST_T; - os_list_container->error = 0; - - return os_list_container; -} - -osi_os_list_t osi_unique_relationship_values(osi_lib_t lib, osi_relationship relationship, int* err) -{ - int len; - struct osi_generic_type * os_list_container; - struct osi_os_list * os_list; - struct osi_internal_os ** os_refs, * os; - struct osi_internal_lib * internal_lib; - - if (!err) - return NULL; - - if (!osi_check_lib(lib) || !osi_valid_os_relationship(relationship)) { - *err = -EINVAL; - return NULL; - } - - internal_lib = lib->backing_object; - len = 0; - - os_list = malloc(sizeof(*os_list)); - os_refs = malloc(sizeof(*os_refs) * internal_lib->num_os); - if (!os_list) { - free(os_list); - free(os_refs); - *err = -ENOMEM; - return NULL; - } - - /* Iterate os list and check against filter (adding to list if passed) */ - list_for_each_entry(os, &internal_lib->os_list, list) { - if (os_participates_in_relationship(os, relationship)) { - os_refs[len] = os; - len += 1; - } - } - - /* Resize the list so we're not wasting memory */ - os_refs = realloc(os_refs, sizeof(*os_refs) * len); - if (!os_refs && len != 0) { - free(os_list); - *err = -ENOMEM; - return NULL; - } - os_list->os_refs = os_refs; - os_list->length = len; - - os_list_container = wrapped_os_list(os_list); - if (!os_list_container) { - free(os_list); - free(os_refs); - *err = -ENOMEM; - return NULL; - } - return os_list_container; -} - -static osi_os_t wrapped_os(struct osi_internal_os * os, int* err) -{ - struct osi_generic_type * os_container; - - os_container = malloc(sizeof(*os_container)); - if (!os_container) { - *err = -ENOMEM; - return NULL; - } - - os_container->backing_object = os; - os_container->initialized = 1; - os_container->type = OSI_OS_T; - os_container->error = 0; - - *err = 0; - return os_container; -} - -osi_os_list_t osi_get_os_list(osi_lib_t lib, osi_filter_t filter, int* err) -{ - int len; - struct osi_generic_type * os_list_container; - struct osi_os_list * os_list; - struct osi_internal_os ** os_refs, * os; - struct osi_internal_lib * internal_lib; - struct osi_internal_filter * internal_filter; - - if (!err) - return NULL; - - if (!osi_check_lib(lib) || - (filter!= NULL && !osi_check_filter(filter)) ) { - *err = -EINVAL; - return NULL; - } - - internal_lib = lib->backing_object; - - if (filter != NULL) - internal_filter = filter->backing_object; - else - internal_filter = NULL; - - len = 0; - - os_list = malloc(sizeof(*os_list)); - os_refs = malloc(sizeof(*os_refs) * internal_lib->num_os); - if (!os_list || !os_refs) { - free(os_list); - free(os_refs); - *err = -ENOMEM; - return NULL; - } - - /* Iterate os list and check against filter (adding to list if passed) */ - list_for_each_entry(os, &internal_lib->os_list, list) { - if (os_passes_filter(os, internal_filter)) { - os_refs[len] = os; - len += 1; - } - } - - /* Resize the list so we're not wasting memory */ - os_refs = realloc(os_refs, sizeof(*os_refs) * len); - if (!os_refs && len != 0) { - free(os_list); - *err = -ENOMEM; - return NULL; - } - os_list->os_refs = os_refs; - os_list->length = len; - - os_list_container = wrapped_os_list(os_list); - if (!os_list_container) { - free(os_list); - free(os_refs); - *err = -ENOMEM; - return NULL; - } - - *err = 0; - return os_list_container; -} - -int osi_free_os_list(osi_os_list_t list) -{ - struct osi_os_list * os_list; - - if (!osi_check_os_list(list)) - return -EINVAL; - - os_list = list->backing_object; - - free(os_list->os_refs); - free(os_list); - free(list); - return 0; -} - -int osi_os_list_length(osi_os_list_t list) -{ - struct osi_os_list * os_list; - - if (!osi_check_os_list(list)) - return -EINVAL; - - os_list = list->backing_object; - return os_list->length; -} - -osi_os_t osi_get_os_by_index(osi_os_list_t list, int idx, int* err) -{ - struct osi_os_list * os_list; - struct osi_internal_os * os; - - if (!err) - return NULL; - - if (!osi_check_os_list(list)) { - *err = -EINVAL; - return NULL; - } - - os_list = list->backing_object; - - /* Check bounds */ - if (idx < 0 || idx >= os_list->length) { - *err = -EINVAL; - return NULL; - } - - os = os_list->os_refs[idx]; - return wrapped_os(os, err); -} - -char* osi_get_os_id(osi_os_t os, int* err) -{ - struct osi_internal_os * internal_os; - char* id; - - if (!err) - return NULL; - - if (!osi_check_os(os)) { - *err = -EINVAL; - return NULL; - } - - internal_os = os->backing_object; - - id = strdup(internal_os->id); - if (!id) { - *err = -ENOMEM; - return NULL; - } - - *err = 0; - return id; -} - -osi_os_t osi_get_os_by_id(osi_lib_t lib, char* id, int* err) -{ - struct osi_internal_os * os = NULL, * test_os; - struct osi_internal_lib * internal_lib; - struct list_head * cursor; - - if (!err) - return NULL; - - if (!osi_check_lib(lib) || !id) { - *err = -EINVAL; - return NULL; - } - - internal_lib = lib->backing_object; - - list_for_each(cursor, &internal_lib->os_list) { - test_os = list_entry(cursor, struct osi_internal_os, list); - if (strcmp(test_os->id, id) == 0) { - os = test_os; - break; - } - } - - if (!os) { - *err = -EINVAL; - return NULL; - } - - return wrapped_os(os, err); -} - -char** osi_get_all_os_property_keys(osi_os_t os, int* num, int* err) -{ - int i; - char** property_keys; - struct osi_internal_os * internal_os; - struct osi_keyval_multi * kv; - - if (!err) - return NULL; - - if (!osi_check_os(os) || !num) { - *err = -EINVAL; - return NULL; - } - - internal_os = os->backing_object; - property_keys = malloc(sizeof(*property_keys) * internal_os->num_params); - if (!property_keys) { - *err = -ENOMEM; - return NULL; - } - - i = 0; - list_for_each_entry(kv, &internal_os->param_list, list) { - if (i == internal_os->num_params) - goto error; /* Should *never* happen */ - - property_keys[i] = strdup(kv->key); - if (!property_keys[i]) - goto error; - i += 1; - } - - *err = 0; - *num = internal_os->num_params; - return property_keys; - -error: - for (i -= 1; i >= 0; i--) - free(property_keys[i]); - free(property_keys); - *err = -ENOMEM; - return NULL; -} - -char** osi_get_os_property_all_values(osi_os_t os, char* propname, int* num, int* err) -{ - struct osi_internal_os * internal_os; - - if (!err) - return NULL; - - if (!osi_check_os(os) || !propname || !num) { - *err = -EINVAL; - return NULL; - } - - internal_os = os->backing_object; - return os_property_all_values(internal_os, propname, num, err); -} - -char* osi_get_os_property_first_value(osi_os_t os, char* propname, int* err) -{ - char* value; - struct osi_internal_os * internal_os; - struct osi_keyval_multi *kv = NULL; - struct osi_keyval_multi *test_kv; - struct list_head * cursor; - struct osi_value * value_container; - - if (!err) - return NULL; - - if (!osi_check_os(os) || !propname) { - *err = -EINVAL; - return NULL; - } - - internal_os = os->backing_object; - - /* First find the appropriate node based on propname */ - list_for_each(cursor, &internal_os->param_list) { - test_kv = list_entry(cursor, struct osi_keyval_multi, list); - if (strcmp(propname, test_kv->key) == 0) { - kv = test_kv; - break; - } - } - if (!kv) { - *err = -EINVAL; - return NULL; - } - - /* Found it, and there is at least one value set */ - cursor = kv->values_list.next; - value_container = list_entry(cursor, struct osi_value, list); - value = strdup(value_container->val); - if (!value) { - *err = -ENOMEM; - return NULL; - } - return value; -} - -osi_os_t osi_get_related_os(osi_os_t os, osi_relationship relationship, int* err) -{ - struct osi_internal_os * internal_os, * target_os; - - if (!err) - return NULL; - - if (!osi_check_os(os) || !osi_valid_os_relationship(relationship)) { - *err = -EINVAL; - return NULL; - } - - internal_os = os->backing_object; - target_os = get_related_os(internal_os, relationship, err); - if (*err != 0) - return NULL; - - return wrapped_os(target_os, err); -} diff --git a/src/osinfo_common.c b/src/osinfo_common.c new file mode 100644 index 0000000..3dc1cc0 --- /dev/null +++ b/src/osinfo_common.c @@ -0,0 +1,349 @@ +#include <osinfo.h> + +static int __osinfoAddDeviceToList(GTree *allSectionsAsList, + gchar *sectionName, + struct __osinfoDeviceLink *deviceLink) +{ + if (!allSectionsAsList || !sectionName || !deviceLink) + return -EINVAL; + + gboolean found; + gpointer origKey, foundValue; + GPtrArray *sectionList; + gchar *sectionNameDup = NULL; + + found = g_tree_lookup_extended(allSectionsAsList, sectionName, &origKey, &foundValue); + if (!found) { + sectionList = g_ptr_array_new(); + sectionNameDup = g_strdup(sectionName); + + if (!sectionList) + goto error_free; + if (!sectionNameDup) { + g_ptr_array_free(sectionList, TRUE); + goto error_free; + } + + g_tree_insert(allSectionsAsList, sectionNameDup, sectionList); + } + else + sectionList = (GPtrArray *) foundValue; + + g_ptr_array_add(sectionList, deviceLink); + return 0; + +error_free: + g_free(sectionNameDup); + return -ENOMEM; +} + +int __osinfoAddDeviceToSection(GTree *allSections, GTree *allSectionsAsList, gchar *sectionName, gchar *id, gchar *driver) +{ + if (!allSections || !sectionName || !id) + return -EINVAL; + + gboolean found; + gpointer origKey, foundValue; + gchar *sectionNameDup = NULL, *idDup = NULL, *driverDup = NULL; + GTree *section; + struct __osinfoDeviceLink *deviceLink; + int ret; + + idDup = g_strdup(id); + driverDup = g_strdup(driver); + deviceLink = g_malloc(sizeof(*deviceLink)); + + if (!idDup || g_strcmp0(driverDup, driver) != 0 || !deviceLink) + goto error_free; + + found = g_tree_lookup_extended(allSections, sectionName, &origKey, &foundValue); + if (!found) { + section = g_tree_new_full(__osinfoStringCompare, NULL, g_free, __osinfoFreeDeviceLink); + sectionNameDup = g_strdup(sectionName); + + if (!section) + goto error_free; + if (!sectionNameDup) { + g_tree_destroy(section); + goto error_free; + } + + g_tree_insert(allSections, sectionNameDup, section); + } + else + section = (GTree *) foundValue; + + deviceLink->driver = driverDup; + g_tree_insert(section, idDup, deviceLink); + + ret = 0; + if (allSectionsAsList) + ret = __osinfoAddDeviceToList(allSectionsAsList, sectionName, deviceLink); + + return ret; + +error_free: + g_free(sectionNameDup); + g_free(idDup); + g_free(driverDup); + g_free(deviceLink); + return -ENOMEM; +} + +void __osinfoClearDeviceSection(GTree *allSections, GTree *allSectionsAsList, gchar *section) +{ + if (!allSections || !section) + return; + + g_tree_remove(allSections, section); + g_tree_remove(allSectionsAsList, section); +} + +void __osinfoFreeDeviceLink(gpointer ptr) +{ + if (!ptr) + return; + struct __osinfoDeviceLink *devLink = (struct __osinfoDeviceLink *) ptr; + g_free(devLink->driver); + g_free(devLink); +} + +void __osinfoFreeDeviceSection(gpointer tree) +{ + if (!tree) + return; + g_tree_destroy((GTree *)tree); +} + +gint __osinfoStringCompare(gconstpointer a, + gconstpointer b, + gpointer data) +{ + // a and b are each gchar *, data is ignored + gchar *str1 = (gchar *) a; + gchar *str2 = (gchar *) b; + return g_strcmp0(str1, str2); +} + +gint __osinfoStringCompareBase(gconstpointer a, + gconstpointer b) +{ + // a and b are each gchar *, data is ignored + gchar *str1 = (gchar *) a; + gchar *str2 = (gchar *) b; + return g_strcmp0(str1, str2); +} + +gint __osinfoIntCompareBase(gconstpointer a, + gconstpointer b) +{ + // a and b are each gchar *, data is ignored + unsigned long int1 = (unsigned long) a; + unsigned long int2 = (unsigned long) b; + return a - b; +} + +gint __osinfoIntCompare(gconstpointer a, + gconstpointer b, + gpointer data) +{ + // a and b are each gchar *, data is ignored + unsigned long int1 = (unsigned long) a; + unsigned long int2 = (unsigned long) b; + return a - b; +} + +void __osinfoFreePtrArray(gpointer ptrarray) +{ + g_ptr_array_free(ptrarray, TRUE); +} + +void __osinfoFreeRelationship(gpointer ptrarray) +{ + if (!ptrarray) + return; + __osinfoFreePtrArray(ptrarray); +} + +void __osinfoFreeParamVals(gpointer ptrarray) +{ + if (!ptrarray) + return; + __osinfoFreePtrArray(ptrarray); +} + +void __osinfoFreeOsLink(gpointer ptr) +{ + if (!ptr) + return; + struct __osinfoOsLink *osLink = (struct __osinfoOsLink *) ptr; + g_free(osLink); +} + +void __osinfoFreeHvSection(gpointer ptr) +{ + if (!ptr) + return; + struct __osinfoHvSection * hvSection = (struct __osinfoHvSection *) ptr; + g_tree_destroy(hvSection->sections); + g_tree_destroy(hvSection->sectionsAsList); + g_free(hvSection); +} + +gboolean __osinfoFilterCheckProperty(gpointer key, gpointer value, gpointer data) +{ + struct __osinfoFilterPassArgs *args; + args = (struct __osinfoFilterPassArgs *) data; + OsinfoEntity *entity = args->entity; + + // Key is property to filter on + // Value is array of values for property + + GPtrArray *filterValues = (GPtrArray *) value; + GPtrArray *entityValues = NULL; + + entityValues = g_tree_lookup(entity->priv->params, key); + if (!entityValues && filterValues->len > 0) { + args->passed = 0; + return TRUE; // not passed + } + + int i; + for (i = 0; i < filterValues->len; i++) { + gchar *currValue = g_ptr_array_index(filterValues, i); + int j, found = 0; + for (j = 0; j < entityValues->len; j++) { + gchar *testValue = g_ptr_array_index(entityValues, j); + if (g_strcmp0(currValue, testValue) == 0) { + found = 1; + break; + } + } + if (found) + continue; + else { + args->passed = 0; + return TRUE; // not passed + } + } + + args->passed = 1; + return FALSE; // continue iterating +} + +int __osinfoEntityPassesFilter(OsinfoFilter *filter, OsinfoEntity *entity) +{ + if (!OSINFO_IS_ENTITY(entity)) + return 0; + + if (!filter) + return 1; + + if (!OSINFO_IS_FILTER(filter)) + return 0; + + struct __osinfoFilterPassArgs args = {0, entity}; + g_tree_foreach(filter->priv->propertyConstraints, __osinfoFilterCheckProperty, &args); + if (args.passed) + return 1; + else + return 0; +} + +int __osinfoDevicePassesFilter(OsinfoFilter *filter, OsinfoDevice *device) +{ + // Check is device + return __osinfoEntityPassesFilter(filter, OSINFO_ENTITY (device)); +} + +gboolean __osinfoFilterCheckRelationships(gpointer key, gpointer value, gpointer data) +{ + struct __osinfoFilterPassArgs *args; + args = (struct __osinfoFilterPassArgs *) data; + OsinfoOs *os = (OsinfoOs *) args->entity; + + // Key is relationship to filter on + // Value is array of oses for relationship + + GPtrArray *filterOses = (GPtrArray *) value; + GPtrArray *oses = NULL; + + oses = g_tree_lookup(os->priv->relationshipsByType, key); + if (!oses && filterOses->len > 0) { + args->passed = 0; + return TRUE; // not passed + } + + int i; + for (i = 0; i < filterOses->len; i++) { + OsinfoOs *currOs = g_ptr_array_index(filterOses, i); + int j, found = 0; + for (j = 0; j < oses->len; j++) { + OsinfoOs *testOs = g_ptr_array_index(oses, j); + if (testOs == currOs) { + found = 1; + break; + } + } + if (found) + continue; + else { + args->passed = 0; + return TRUE; // not passed + } + } + + args->passed = 1; + return FALSE; // continue iterating +} + +int __osinfoOsPassesFilter(OsinfoFilter *filter, OsinfoOs *os) +{ + if (!OSINFO_IS_OS(os)) + return 0; + + if (!filter) + return 1; + + if (!OSINFO_IS_FILTER(filter)) + return 0; + + int pass = __osinfoEntityPassesFilter(filter, OSINFO_ENTITY (os)); + if (!pass) + return 0; + + struct __osinfoFilterPassArgs args = {0, (OsinfoEntity *) os}; + g_tree_foreach(filter->priv->relationshipConstraints, __osinfoFilterCheckRelationships, &args); + if (args.passed) + return 1; + else + return 0; +} + +int __osinfoHypervisorPassesFilter(OsinfoFilter *filter, OsinfoHypervisor *hypervisor) +{ + return __osinfoEntityPassesFilter(filter, OSINFO_ENTITY (hypervisor)); +} + +int __osinfoCheckGErrorParamValid(GError **err) +{ + // If err is not null and *err is not null, then invalid + if (err && *err) + return 0; + else return 1; +} + +int __osinfoCheckRelationshipValid(osinfoRelationship relshp) +{ + return (relshp > RELATIONSHIP_MIN && relshp < RELATIONSHIP_MAX); +} + +gchar *__osinfoErrorToString(int err) +{ + switch (err) { + case -ENOMEM: + return OSINFO_NO_MEM; + default: + return OSINFO_OTHER; + } +} diff --git a/src/osi_dataread.c b/src/osinfo_dataread.c index 4af4eab..e1e0d52 100644 --- a/src/osi_dataread.c +++ b/src/osinfo_dataread.c @@ -4,11 +4,9 @@ #include <dirent.h> #include <errno.h> #include <unistd.h> -#include <libosinfo.h> #include <libxml/xmlreader.h> -#include "list.h" -#include "osi_internal_types.h" +#include <osinfo.h> #ifdef LIBXML_READER_ENABLED @@ -34,142 +32,155 @@ * object, is the same as the starting tag for the object). */ +struct __osinfoDbRet { + OsinfoDb *db; + int *ret; +}; -static int resolve_section_devices(struct osi_internal_lib * lib, - struct osi_device_section * section) +static gboolean __osinfoResolveDeviceLink(gpointer key, gpointer value, gpointer data) { - struct list_head * cursor; - struct osi_device_link * dev_link; - struct osi_internal_dev * dev; + gchar *id = (gchar *) key; + struct __osinfoDeviceLink *devLink = (struct __osinfoDeviceLink *) value; + struct __osinfoDbRet *dbRet = (struct __osinfoDbRet *) data; + OsinfoDb *db = dbRet->db; + int *ret = dbRet->ret; - if (!section) - return -EINVAL; - - list_for_each(cursor, §ion->devices_list) { - dev_link = list_entry(cursor, struct osi_device_link, list); - dev = __osi_find_dev_by_id(lib, dev_link->id); - if (!dev) - return -EINVAL; - dev_link->dev = dev; + OsinfoDevice *dev = g_tree_lookup(db->priv->devices, id); + if (!dev) { + *ret = -EINVAL; + return TRUE; } - return 0; + devLink->dev = dev; + *ret = 0; + return FALSE; } -static int resolve_hv_link(struct osi_internal_lib * lib, - struct osi_hypervisor_link * hv_link) +static gboolean __osinfoResolveSectionDevices(gpointer key, gpointer value, gpointer data) { - int ret; - struct list_head * cursor; - struct osi_device_section * section; - struct osi_internal_hv * hv; - - list_for_each(cursor, &hv_link->dev_sections_list) { - section = list_entry(cursor, struct osi_device_section, list); - ret = resolve_section_devices(lib, section); - if (ret != 0) - return ret; + struct __osinfoDbRet *dbRet = (struct __osinfoDbRet *) data; + OsinfoDb *db = dbRet->db; + int *ret = dbRet->ret; + GTree *section = (GTree *) value; + if (!section) { + *ret = -EINVAL; + return TRUE; } - hv = __osi_find_hv_by_id(lib, hv_link->hv_id); - if (!hv) - return -EINVAL; - - hv_link->hv = hv; - return 0; + g_tree_foreach(section, __osinfoResolveDeviceLink, dbRet); + if (*ret) + return TRUE; + return FALSE; } -static int resolve_os_link(struct osi_internal_lib * lib, - struct osi_os_link * os_link) +static gboolean __osinfoResolveHvLink(gpointer key, gpointer value, gpointer data) { - struct osi_internal_os * target_os; - - target_os = __osi_find_os_by_id(lib, os_link->dobj_os_id); - if (!target_os) - return -EINVAL; + gchar *hvId = (gchar *) key; + struct __osinfoDbRet *dbRet = (struct __osinfoDbRet *) data; + OsinfoDb *db = dbRet->db; + int *ret = dbRet->ret; + struct __osinfoHvSection *hvSection = (struct __osinfoHvSection *) value; + OsinfoHypervisor *hv; + + g_tree_foreach(hvSection->sections, __osinfoResolveSectionDevices, dbRet); + if (*ret) + return TRUE; + + hv = g_tree_lookup(db->priv->hypervisors, hvId); + if (!hv) { + *ret = -EINVAL; + return TRUE; + } - os_link->direct_object_os = target_os; - return 0; + hvSection->hv = hv; + *ret = 0; + return FALSE; } -static int fix_os_links(struct osi_internal_lib * lib, - struct osi_internal_os * os) +static gboolean __osinfoResolveOsLink(gpointer key, gpointer value, gpointer data) { - int ret; - struct list_head * cursor; - struct osi_device_section * section; - struct osi_hypervisor_link * hv_link; - struct osi_os_link * os_link; - - list_for_each(cursor, &os->dev_sections_list) { - section = list_entry(cursor, struct osi_device_section, list); - ret = resolve_section_devices(lib, section); - if (ret != 0) - return ret; + gchar *targetOsId = (gchar *) key; + struct __osinfoDbRet *dbRet = (struct __osinfoDbRet *) data; + OsinfoDb *db = dbRet->db; + int *ret = dbRet->ret; + struct __osinfoOsLink *osLink = (struct __osinfoOsLink *) value; + + OsinfoOs *targetOs; + targetOs = g_tree_lookup(db->priv->oses, targetOsId); + if (!targetOs) { + *ret = -EINVAL; + return TRUE; } - list_for_each(cursor, &os->hypervisor_info_list) { - hv_link = list_entry(cursor, struct osi_hypervisor_link, list); - ret = resolve_hv_link(lib, hv_link); - if (ret != 0) - return ret; - } + osLink->directObjectOs = targetOs; + *ret = 0; + return FALSE; +} - list_for_each(cursor, &os->relationships_list) { - os_link = list_entry(cursor, struct osi_os_link, list); - ret = resolve_os_link(lib, os_link); - if (ret != 0) - return ret; +static gboolean __osinfoFixOsLinks(gpointer key, gpointer value, gpointer data) +{ + struct __osinfoDbRet *dbRet = (struct __osinfoDbRet *) data; + OsinfoDb *db = dbRet->db; + int *ret = dbRet->ret; + OsinfoOs *os = OSINFO_OS(value); + if (!os) { + *ret = -EINVAL; + return TRUE; } - return 0; + g_tree_foreach(os->priv->sections, __osinfoResolveSectionDevices, dbRet); + if (*ret) + return TRUE; + + g_tree_foreach(os->priv->relationshipsByOs, __osinfoResolveOsLink, dbRet); + if (*ret) + return TRUE; + + g_tree_foreach(os->priv->hypervisors, __osinfoResolveHvLink, dbRet); + if (*ret) + return TRUE; + + *ret = 0; + return FALSE; } -static int fix_hv_links(struct osi_internal_lib * lib, - struct osi_internal_hv * hv) +static gboolean __osinfoFixHvLinks(gpointer key, gpointer value, gpointer data) { - int ret; - struct list_head * cursor; - struct osi_device_section * section; - - list_for_each(cursor, &hv->dev_sections_list) { - section = list_entry(cursor, struct osi_device_section, list); - ret = resolve_section_devices(lib, section); - if (ret != 0) - return ret; + struct __osinfoDbRet *dbRet = (struct __osinfoDbRet *) data; + OsinfoDb *db = dbRet->db; + int *ret = dbRet->ret; + OsinfoHypervisor *hv = OSINFO_HYPERVISOR(value); + if (!hv) { + *ret = -EINVAL; + return TRUE; } - return 0; + g_tree_foreach(hv->priv->sections, __osinfoResolveSectionDevices, dbRet); + if (*ret) + return TRUE; + return FALSE; } -static int fix_obj_links(struct osi_internal_lib * lib) +static int __osinfoFixObjLinks(OsinfoDb *db) { - struct list_head * cursor; - struct osi_internal_hv * hv; - struct osi_internal_os * os; + OsinfoHypervisor *hv; + OsinfoOs *os; int ret; - if (!lib) + if (!OSINFO_IS_DB(db)) return -EINVAL; - list_for_each(cursor, &lib->hypervisor_list) { - hv = list_entry(cursor, struct osi_internal_hv, list); - ret = fix_hv_links(lib, hv); - if (ret != 0) - return ret; - } + struct __osinfoDbRet dbRet = {db, &ret}; - list_for_each(cursor, &lib->os_list) { - os = list_entry(cursor, struct osi_internal_os, list); - ret = fix_os_links(lib, os); - if (ret != 0) - return ret; - } + g_tree_foreach(db->priv->hypervisors, __osinfoFixHvLinks, &dbRet); + if (ret) + return ret; + g_tree_foreach(db->priv->oses, __osinfoFixOsLinks, &dbRet); - return 0; + return ret; } -static int process_tag(xmlTextReaderPtr reader, char** ptr_to_key, char** ptr_to_val) +static int __osinfoProcessTag(xmlTextReaderPtr reader, char** ptr_to_key, char** ptr_to_val) { int node_type, ret, err = 0; char* key = NULL; @@ -235,36 +246,25 @@ error: return err; } -static int process_dev_section(xmlTextReaderPtr reader, - struct list_head * head, - int * num) +static int __osinfoProcessDevSection(xmlTextReaderPtr reader, + GTree *section, GTree *sectionAsList) { int err, empty, node_type; - char * type, * id, * key = NULL, * driver = NULL; + char * sectionType, * id, * key = NULL, * driver = NULL; const char * name; - struct osi_device_section * section; - struct osi_device_link * dev_link; - - type = xmlTextReaderGetAttribute(reader, "type"); - empty = xmlTextReaderIsEmptyElement(reader); - if (!type) + if (!section) return -EINVAL; - /* Alloc structure for section and store type */ - section = malloc(sizeof(*section)); - if (!section) { - free(type); - return -ENOMEM; - } + sectionType = xmlTextReaderGetAttribute(reader, "type"); + empty = xmlTextReaderIsEmptyElement(reader); - section->type = type; - section->num_devices = 0; - INIT_LIST_HEAD(§ion->devices_list); + if (!sectionType) + return -EINVAL; /* If no devices in section then we are done */ if (empty) - goto finished; + return 0; /* Otherwise, read in devices and add to section */ for (;;) { @@ -301,42 +301,36 @@ static int process_dev_section(xmlTextReaderPtr reader, } if (!empty) { - err = process_tag(reader, &key, &driver); + err = __osinfoProcessTag(reader, &key, &driver); if (err != 0 || !key || !driver) goto error; free(key); key = NULL; /* In case the next malloc fails, avoid a double free */ } - /* Store link to device in structure */ - dev_link = malloc(sizeof(*dev_link)); - if (!dev_link) { - err = -ENOMEM; - free(id); + // Alright, we have the id and driver + err = __osinfoAddDeviceToSection(section, sectionAsList, sectionType, id, driver); + free (driver); + driver = NULL; + free (id); + id = NULL; + if (err != 0) goto error; - } - - dev_link->id = id; - dev_link->driver = driver; - dev_link->dev = NULL; - section->num_devices += 1; - list_add_tail(&dev_link->list, §ion->devices_list); } + free(sectionType); finished: - list_add_tail(§ion->list, head); - *num += 1; return 0; error: + free(sectionType); free(key); free(driver); - __osi_free_device_section(section); return err; } -static int process_os_hv_link(xmlTextReaderPtr reader, - struct osi_internal_os *os) +static int __osinfoProcessOsHvLink(xmlTextReaderPtr reader, + OsinfoOs *os) { /* * Get id for hypervisor else fail @@ -352,7 +346,7 @@ static int process_os_hv_link(xmlTextReaderPtr reader, int empty, node_type, err; char* id; const xmlChar* name; - struct osi_hypervisor_link * hv_link; + struct __osinfoHvSection *hvSection; id = xmlTextReaderGetAttribute(reader, "id"); empty = xmlTextReaderIsEmptyElement(reader); @@ -360,17 +354,10 @@ static int process_os_hv_link(xmlTextReaderPtr reader, if (!id) return -EINVAL; - hv_link = malloc(sizeof(*hv_link)); - if (!hv_link) { - free(id); + hvSection = __osinfoAddHypervisorSectionToOs(os, id); + free(id); + if (!hvSection) return -EINVAL; - } - - hv_link->hv_id = id; - hv_link->os = os; - hv_link->hv = NULL; /* Will resolve link later */ - hv_link->num_dev_sections = 0; - INIT_LIST_HEAD(&hv_link->dev_sections_list); if (empty) goto finished; @@ -405,26 +392,23 @@ static int process_os_hv_link(xmlTextReaderPtr reader, } /* Process device type info for this <os, hv> combination */ - err = process_dev_section(reader, &hv_link->dev_sections_list, &hv_link->num_dev_sections); + err = __osinfoProcessDevSection(reader, hvSection->sections, hvSection->sectionsAsList); if (err != 0) goto error; } finished: - os->num_hypervisors += 1; - list_add_tail(&hv_link->list, &os->hypervisor_info_list); return 0; error: - __osi_cleanup_hv_link(hv_link); return err; } -static int process_os_relationship(xmlTextReaderPtr reader, - struct osi_internal_os * os, - osi_relationship relationship) +static int __osinfoProcessOsRelationship(xmlTextReaderPtr reader, + OsinfoOs *os, + osinfoRelationship relationship) { - int empty; + int empty, ret; char* id; struct osi_os_link * os_link; @@ -435,23 +419,12 @@ static int process_os_relationship(xmlTextReaderPtr reader, return -EINVAL; } - os_link = malloc(sizeof(*os_link)); - if (!os_link) { - free(id); - return -ENOMEM; - } - - os_link->subject_os = os; - os_link->verb = relationship; - os_link->direct_object_os = NULL; /* will resolve after reading all data */ - os_link->dobj_os_id = id; - - os->num_relationships += 1; - list_add_tail(&os_link->list, &os->relationships_list); - return 0; + ret = __osinfoAddOsRelationship (os, id, relationship); + free(id); + return ret; } -static int process_os(struct osi_internal_lib * lib, +static int __osinfoProcessOs(OsinfoDb *db, xmlTextReaderPtr reader) { /* Cursor is at start of (possibly empty) os node */ @@ -466,7 +439,7 @@ static int process_os(struct osi_internal_lib * lib, int empty, node_type, err, ret; char* id, * key = NULL, * val = NULL; const xmlChar* name; - struct osi_internal_os * os; + OsinfoOs *os; id = xmlTextReaderGetAttribute(reader, "id"); empty = xmlTextReaderIsEmptyElement(reader); @@ -474,22 +447,10 @@ static int process_os(struct osi_internal_lib * lib, if (!id) return -EINVAL; - os = malloc(sizeof(*os)); - if (!os) { - free(id); + os = g_object_new(OSINFO_TYPE_OS, "id", id, "db", db, NULL); + free(id); + if (!os) return -ENOMEM; - } - - os->id = id; - os->num_params = 0; - INIT_LIST_HEAD(&os->param_list); - os->num_hypervisors = 0; - INIT_LIST_HEAD(&os->hypervisor_info_list); - os->num_dev_sections = 0; - INIT_LIST_HEAD(&os->dev_sections_list); - os->num_relationships = 0; - INIT_LIST_HEAD(&os->relationships_list); - os->lib = lib; if (empty) goto finished; @@ -533,38 +494,37 @@ static int process_os(struct osi_internal_lib * lib, if (strcmp(name, "section") == 0) { /* Node is start of device section for os */ - err = process_dev_section(reader, &os->dev_sections_list, &os->num_dev_sections); + err = __osinfoProcessDevSection(reader, (OSINFO_OS(os))->priv->sections, (OSINFO_OS(os))->priv->sectionsAsList); if (err != 0) goto cleanup_error; } else if (strcmp(name, "hypervisor") == 0) { - err = process_os_hv_link(reader, os); + err = __osinfoProcessOsHvLink(reader, os); if (err != 0) goto cleanup_error; } else if (strcmp(name, "upgrades") == 0) { - err = process_os_relationship(reader, os, UPGRADES); + err = __osinfoProcessOsRelationship(reader, os, UPGRADES); if (err != 0) goto cleanup_error; } else if (strcmp(name, "clones") == 0) { - err = process_os_relationship(reader, os, CLONES); + err = __osinfoProcessOsRelationship(reader, os, CLONES); if (err != 0) goto cleanup_error; } else if (strcmp(name, "derives-from") == 0) { - err = process_os_relationship(reader, os, DERIVES_FROM); + err = __osinfoProcessOsRelationship(reader, os, DERIVES_FROM); if (err != 0) goto cleanup_error; } else { /* Node is start of element of known name */ - err = process_tag(reader, &key, &val); + err = __osinfoProcessTag(reader, &key, &val); if (err != 0 || !key || !val) goto cleanup_error; - /* Store <key,val> in device param_list */ - err = __osi_store_keyval(key, val, &os->param_list, &os->num_params); + err = __osinfoAddParam(OSINFO_ENTITY(os), key, val); if (err != 0) goto cleanup_error; @@ -574,17 +534,16 @@ static int process_os(struct osi_internal_lib * lib, } finished: - lib->num_os += 1; - list_add_tail(&os->list, &lib->os_list); + __osinfoAddOsToDb(db, os); return 0; /* At end, cursor is at end of os node */ cleanup_error: - __osi_free_os(os); + g_object_unref(os); return err; } -static int process_hypervisor(struct osi_internal_lib * lib, +static int __osinfoProcessHypervisor(OsinfoDb *db, xmlTextReaderPtr reader) { /* Cursor is at start of (possibly empty) hypervisor node */ @@ -598,9 +557,9 @@ static int process_hypervisor(struct osi_internal_lib * lib, */ int empty, node_type, err, ret; - char* id, * key = NULL, * val = NULL; + char* id; const xmlChar* name; - struct osi_internal_hv * hv; + OsinfoHypervisor *hv; id = xmlTextReaderGetAttribute(reader, "id"); empty = xmlTextReaderIsEmptyElement(reader); @@ -608,19 +567,13 @@ static int process_hypervisor(struct osi_internal_lib * lib, if (!id) return -EINVAL; - hv = malloc(sizeof(*hv)); + + hv = g_object_new(OSINFO_TYPE_HYPERVISOR, "id", id, "db", db, NULL); + free(id); if (!hv) { - free(id); return -ENOMEM; } - hv->id = id; - hv->num_params = 0; - INIT_LIST_HEAD(&hv->param_list); - hv->num_dev_sections = 0; - INIT_LIST_HEAD(&hv->dev_sections_list); - hv->lib = lib; - if (empty) goto finished; @@ -671,41 +624,38 @@ static int process_hypervisor(struct osi_internal_lib * lib, if (strcmp(name, "section") == 0) { /* Node is start of device section for hv */ - err = process_dev_section(reader, &hv->dev_sections_list, &hv->num_dev_sections); + err = __osinfoProcessDevSection(reader, (OSINFO_HYPERVISOR(hv))->priv->sections, (OSINFO_HYPERVISOR(hv))->priv->sectionsAsList); if (err != 0) goto cleanup_error; } else { /* Node is start of element of known name */ - err = process_tag(reader, &key, &val); - if (err != 0 || !key || !val) - goto cleanup_error; - - /* Store <key,val> in device param_list */ - err = __osi_store_keyval(key, val, &hv->param_list, &hv->num_params); + char *key = NULL, *val = NULL; + err = __osinfoProcessTag(reader, &key, &val); if (err != 0) goto cleanup_error; + + err = __osinfoAddParam(OSINFO_ENTITY(hv), key, val); free(key); free(val); + if (err != 0) + goto cleanup_error; } } finished: - lib->num_hypervisors += 1; - list_add_tail(&hv->list, &lib->hypervisor_list); + __osinfoAddHypervisorToDb(db, hv); return 0; /* At end, cursor is at end of hv node */ cleanup_error: - free(key); - free(val); - __osi_free_hv(hv); + g_object_unref(hv); return err; } -static int process_device(struct osi_internal_lib * lib, - xmlTextReaderPtr reader) +static int __osinfoProcessDevice(OsinfoDb *db, + xmlTextReaderPtr reader) { /* Cursor is at start of (possibly empty) device node */ @@ -720,7 +670,7 @@ static int process_device(struct osi_internal_lib * lib, int empty, node_type, err, ret; char* id, * key, * val; const xmlChar* name; - struct osi_internal_dev * dev; + OsinfoDevice *dev; id = xmlTextReaderGetAttribute(reader, "id"); empty = xmlTextReaderIsEmptyElement(reader); @@ -728,17 +678,13 @@ static int process_device(struct osi_internal_lib * lib, if (!id) return -EINVAL; - dev = malloc(sizeof(*dev)); + dev = g_object_new(OSINFO_TYPE_DEVICE, "id", id, "db", db, NULL); + free(id); if (!dev) { - free(id); + // TODO: How do errors in gobject creation manifest themselves? return -ENOMEM; } - dev->id = id; - dev->num_params = 0; - INIT_LIST_HEAD(&dev->param_list); - dev->lib = lib; - if (empty) goto finished; @@ -780,12 +726,11 @@ static int process_device(struct osi_internal_lib * lib, continue; /* Node is start of element of known name */ - err = process_tag(reader, &key, &val); + err = __osinfoProcessTag(reader, &key, &val); if (err != 0 || !key || !val) goto cleanup_error; - /* Store <key,val> in device param_list */ - err = __osi_store_keyval(key, val, &dev->param_list, &dev->num_params); + err = __osinfoAddParam(OSINFO_ENTITY(dev), key, val); if (err != 0) goto cleanup_error; @@ -794,20 +739,20 @@ static int process_device(struct osi_internal_lib * lib, } finished: - list_add_tail(&dev->list, &lib->device_list); - lib->num_devices += 1; + // Add dev to db + __osinfoAddDeviceToDb(db, dev); return 0; /* At end, cursor is at end of device node */ cleanup_error: free(key); free(val); - __osi_free_device(dev); + g_object_unref(dev); return err; } -static int process_file(struct osi_internal_lib * lib, - xmlTextReaderPtr reader) +static int __osinfoProcessFile(OsinfoDb *db, + xmlTextReaderPtr reader) { /* * File assumed to contain data in XML format. All data @@ -872,17 +817,17 @@ static int process_file(struct osi_internal_lib * lib, /* Process element node */ if (strcmp(name, "device") == 0) { - err = process_device(lib, reader); + err = __osinfoProcessDevice(db, reader); if (err != 0) goto cleanup_error; } else if (strcmp(name, "hypervisor") == 0) { - err = process_hypervisor(lib, reader); + err = __osinfoProcessHypervisor(db, reader); if (err != 0) goto cleanup_error; } else if (strcmp(name, "os") == 0) { - err = process_os(lib, reader); + err = __osinfoProcessOs(db, reader); if (err != 0) goto cleanup_error; } @@ -896,13 +841,13 @@ static int process_file(struct osi_internal_lib * lib, return 0; cleanup_error: - __osi_free_lib(lib); + // Db will be unsatisfactorily initiated, caller will call unref to clean it return err; } -static int read_data_file(struct osi_internal_lib *lib, - const char *dir, - const char *filename) +static int __osinfoReadDataFile(OsinfoDb *db, + const char *dir, + const char *filename) { int ret; xmlTextReaderPtr reader; @@ -917,31 +862,29 @@ static int read_data_file(struct osi_internal_lib *lib, if (!reader) { return -EINVAL; } - ret = process_file(lib, reader); + ret = __osinfoProcessFile(db, reader); xmlFreeTextReader(reader); return ret; } -int osi_initialize_data(struct osi_internal_lib * internal_lib, char* data_dir) +int __osinfoInitializeData(OsinfoDb *db) { int ret; DIR* dir; struct dirent *dp; + char *backingDir; + g_object_get(G_OBJECT(db), "backing-dir", &backingDir, NULL); + /* Initialize library and check version */ LIBXML_TEST_VERSION /* Get directory with backing data. Defaults to CWD */ - if (!data_dir) - data_dir = "."; - - if (!data_dir) { - ret = -errno; - goto cleanup; - } + if (!backingDir) + backingDir = "."; /* Get XML files in directory */ - dir = opendir(data_dir); + dir = opendir(backingDir); if (!dir) { ret = errno; goto cleanup; @@ -950,21 +893,22 @@ int osi_initialize_data(struct osi_internal_lib * internal_lib, char* data_dir) while ((dp=readdir(dir)) != NULL) { if (dp->d_type != DT_REG) continue; - ret = read_data_file(internal_lib, data_dir, dp->d_name); + ret = __osinfoReadDataFile(db, backingDir, dp->d_name); if (ret != 0) break; } closedir(dir); if (ret == 0) - ret = fix_obj_links(internal_lib); + ret = __osinfoFixObjLinks(db); cleanup: xmlCleanupParser(); + g_free(backingDir); return ret; } #else -int osi_initialize_data(struct osi_internal_lib * internal_lib) +int __osinfoInitializeData(OsinfoDb *db) { return -ENOSYS; } diff --git a/src/osinfo_db.c b/src/osinfo_db.c new file mode 100644 index 0000000..f78d241 --- /dev/null +++ b/src/osinfo_db.c @@ -0,0 +1,555 @@ +#include <osinfo.h> + +G_DEFINE_TYPE (OsinfoDb, osinfo_db, G_TYPE_OBJECT); + +#define OSINFO_DB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_DB, OsinfoDbPrivate)) + +static void osinfo_db_set_property(GObject * object, guint prop_id, + const GValue * value, + GParamSpec * pspec); +static void osinfo_db_get_property(GObject * object, guint prop_id, + GValue * value, + GParamSpec * pspec); +static void osinfo_db_finalize (GObject *object); + +enum OSI_DB_PROPERTIES { + OSI_DB_PROP_0, + + OSI_DB_BACKING_DIR, + OSI_DB_LIBVIRT_VER, + OSI_DB_ERROR +}; + +static void +osinfo_db_finalize (GObject *object) +{ + OsinfoDb *self = OSINFO_DB (object); + + g_free (self->priv->backing_dir); + g_free (self->priv->libvirt_ver); + + g_tree_destroy(self->priv->devices); + g_tree_destroy(self->priv->hypervisors); + g_tree_destroy(self->priv->oses); + + /* Chain up to the parent class */ + G_OBJECT_CLASS (osinfo_db_parent_class)->finalize (object); +} + +static void +osinfo_db_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + OsinfoDb *self = OSINFO_DB (object); + + switch (property_id) + { + case OSI_DB_BACKING_DIR: + g_free(self->priv->backing_dir); + self->priv->backing_dir = g_value_dup_string (value); + break; + + case OSI_DB_LIBVIRT_VER: + g_free(self->priv->libvirt_ver); + self->priv->libvirt_ver = g_value_dup_string (value); + break; + + case OSI_DB_ERROR: + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +osinfo_db_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + OsinfoDb *self = OSINFO_DB (object); + + switch (property_id) + { + case OSI_DB_BACKING_DIR: + g_value_set_string (value, self->priv->backing_dir); + break; + + case OSI_DB_LIBVIRT_VER: + g_value_set_string (value, self->priv->libvirt_ver); + break; + + case OSI_DB_ERROR: + g_value_set_pointer(value, self->priv->error); + break; + + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* Init functions */ +static void +osinfo_db_class_init (OsinfoDbClass *klass) +{ + GObjectClass *g_klass = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + g_klass->set_property = osinfo_db_set_property; + g_klass->get_property = osinfo_db_get_property; + g_klass->finalize = osinfo_db_finalize; + + pspec = g_param_spec_string ("backing-dir", + "Backing directory", + "Contains backing data store.", + NULL /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (g_klass, + OSI_DB_BACKING_DIR, + pspec); + + pspec = g_param_spec_string ("libvirt-ver", + "Libvirt version", + "Libvirt version user is interested in", + NULL /* default value */, + G_PARAM_READWRITE); + g_object_class_install_property (g_klass, + OSI_DB_LIBVIRT_VER, + pspec); + + pspec = g_param_spec_pointer ("error", + "Error", + "GError object for db", + G_PARAM_READABLE); + g_object_class_install_property (g_klass, + OSI_DB_ERROR, + pspec); + + g_type_class_add_private (klass, sizeof (OsinfoDbPrivate)); +} + + +static void +osinfo_db_init (OsinfoDb *self) +{ + OsinfoDbPrivate *priv; + int ret; + self->priv = priv = OSINFO_DB_GET_PRIVATE(self); + + self->priv->devices = g_tree_new_full(__osinfoStringCompare, NULL, g_free, g_object_unref); + self->priv->hypervisors = g_tree_new_full(__osinfoStringCompare, NULL, g_free, g_object_unref); + self->priv->oses = g_tree_new_full(__osinfoStringCompare, NULL, g_free, g_object_unref); + + self->priv->error = NULL; + self->priv->ready = 0; +} + +/** PUBLIC METHODS */ + +int osinfoInitializeDb(OsinfoDb *self, GError **err) +{ + int ret; + // And now read in data. + ret = __osinfoInitializeData(self); + if (ret != 0) { + self->priv->ready = 0; + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, "Error during reading data"); + } + else + self->priv->ready = 1; + return ret; +} + +OsinfoHypervisor *osinfoGetHypervisorById(OsinfoDb *self, gchar *id, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_DB(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DB); + return NULL; + } + + if (!id) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_ID); + return NULL; + } + + return g_tree_lookup(self->priv->hypervisors, id); +} + +OsinfoDevice *osinfoGetDeviceById(OsinfoDb *self, gchar *id, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_DB(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DB); + return NULL; + } + + if (!id) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_ID); + return NULL; + } + + return g_tree_lookup(self->priv->devices, id); +} + +OsinfoOs *osinfoGetOsById(OsinfoDb *self, gchar *id, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_DB(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DB); + return NULL; + } + + if (!id) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_ID); + return NULL; + } + + return g_tree_lookup(self->priv->oses, id); +} + +static gboolean __osinfoFilteredAddToList(gpointer key, gpointer value, gpointer data) +{ + struct __osinfoPopulateListArgs *args; + args = (struct __osinfoPopulateListArgs *) data; + OsinfoFilter *filter = args->filter; + OsinfoList *list = args->list; + GError **err = args->err; + + // Key is string ID, value is pointer to entity + OsinfoEntity *entity = (OsinfoEntity *) value; + if (__osinfoEntityPassesFilter(filter, entity)) { + __osinfoListAdd(list, entity); + } + + args->errcode = 0; + + return FALSE; // continue iteration +} + +static int __osinfoPopulateList(GTree *entities, OsinfoList *newList, OsinfoFilter *filter, GError **err) +{ + struct __osinfoPopulateListArgs args = {err, 0, filter, newList}; + g_tree_foreach(entities, __osinfoFilteredAddToList, &args); + return args.errcode; +} + +OsinfoOsList *osinfoGetOsList(OsinfoDb *self, OsinfoFilter *filter, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_DB(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DB); + return NULL; + } + + if (filter && !OSINFO_IS_FILTER(filter)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + // Create list + OsinfoOsList *newList = g_object_new(OSINFO_TYPE_OSLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + ret = __osinfoPopulateList(self->priv->oses, OSINFO_LIST (newList), filter, err); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} + +OsinfoHypervisorList *osinfoGetHypervisorList(OsinfoDb *self, OsinfoFilter *filter, GError **err) +{ + if (!OSINFO_IS_DB(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DB); + return NULL; + } + + if (filter && !OSINFO_IS_FILTER(filter)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + // Create list + OsinfoHypervisorList *newList = g_object_new(OSINFO_TYPE_HYPERVISORLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + ret = __osinfoPopulateList(self->priv->hypervisors, OSINFO_LIST (newList), filter, err); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} + +OsinfoDeviceList *osinfoGetDeviceList(OsinfoDb *self, OsinfoFilter *filter, GError **err) +{ + if (!OSINFO_IS_DB(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DB); + return NULL; + } + + if (filter && !OSINFO_IS_FILTER(filter)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + // Create list + OsinfoDeviceList *newList = g_object_new(OSINFO_TYPE_DEVICELIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + ret = __osinfoPopulateList(self->priv->devices, OSINFO_LIST (newList), filter, err); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} + +gboolean __osinfoGetPropertyValuesInEntity(gpointer key, gpointer value, gpointer data) +{ + struct __osinfoPopulateValuesArgs *args; + args = (struct __osinfoPopulateValuesArgs *) data; + GTree *values = args->values; + GError **err = args->err; + gchar *property = args->property; + + OsinfoEntity *entity = OSINFO_ENTITY (value); + GPtrArray *valueArray = NULL; + + valueArray = g_tree_lookup(entity->priv->params, property); + if (valueArray) + return FALSE; // No values here, skip + + int i; + for (i = 0; i < valueArray->len; i++) { + gchar *currValue = g_ptr_array_index(valueArray, i); + void *test = g_tree_lookup(values, currValue); + if (test) + continue; + gchar *dupValue = g_strdup(currValue); + if (!dupValue) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + args->errcode = -ENOMEM; + return TRUE; + } + + // Add to tree with dummy value + g_tree_insert(values, dupValue, (gpointer) 1); + } + + return FALSE; // Continue iterating +} + +static gboolean __osinfoPutKeysInList(gpointer key, gpointer value, gpointer data) +{ + gchar *currValue = (gchar *) key; + GPtrArray *valuesList = (GPtrArray *) data; + + g_ptr_array_add(valuesList, currValue); + return FALSE; // keep iterating +} + +static gboolean __osinfoFreeKeys(gpointer key, gpointer value, gpointer data) +{ + g_free(key); + return FALSE; // keep iterating +} + +static GPtrArray *__osinfoUniqueValuesForPropertyInEntity(GTree *entities, gchar *propName, GError **err) +{ + GTree *values = g_tree_new(__osinfoStringCompareBase); + if (!values) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + struct __osinfoPopulateValuesArgs args = {err, 0, values, propName}; + g_tree_foreach(entities, __osinfoGetPropertyValuesInEntity, &args); + + if (args.errcode != 0) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), args.errcode, __osinfoErrorToString(args.errcode)); + g_tree_foreach(values, __osinfoFreeKeys, NULL); + g_tree_destroy(values); + return NULL; + } + + // For each key in tree, add to gptrarray + GPtrArray *valuesList = g_ptr_array_sized_new(g_tree_nnodes(values)); + if (!valuesList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + g_tree_foreach(values, __osinfoFreeKeys, NULL); + g_tree_destroy(values); + return NULL; + } + + g_tree_foreach(values, __osinfoPutKeysInList, valuesList); + g_tree_destroy(values); + return valuesList; +} + +// Get me all unique values for property "vendor" among operating systems +GPtrArray *osinfoUniqueValuesForPropertyInOs(OsinfoDb *self, gchar *propName, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_DB(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DB); + return NULL; + } + + if (!propName) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_PROPNAME); + return NULL; + } + + return __osinfoUniqueValuesForPropertyInEntity(self->priv->oses, propName, err); +} + +// Get me all unique values for property "vendor" among hypervisors +GPtrArray *osinfoUniqueValuesForPropertyInHv(OsinfoDb *self, gchar *propName, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_DB(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DB); + return NULL; + } + + if (!propName) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_PROPNAME); + return NULL; + } + + return __osinfoUniqueValuesForPropertyInEntity(self->priv->hypervisors, propName, err); +} + +// Get me all unique values for property "vendor" among devices +GPtrArray *osinfoUniqueValuesForPropertyInDev(OsinfoDb *self, gchar *propName, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_DB(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DB); + return NULL; + } + + if (!propName) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_PROPNAME); + return NULL; + } + + return __osinfoUniqueValuesForPropertyInEntity(self->priv->devices, propName, err); +} + +static gboolean __osinfoAddOsIfRelationship(gpointer key, gpointer value, gpointer data) +{ + OsinfoOs *os = (OsinfoOs *) value; + struct __osinfoOsCheckRelationshipArgs *args; + args = (struct __osinfoOsCheckRelationshipArgs *) data; + GError **err = args->err; + OsinfoList *list = args->list; + + GPtrArray *relatedOses = NULL; + relatedOses = g_tree_lookup(os->priv->relationshipsByType, (gpointer) args->relshp); + if (relatedOses) { + __osinfoListAdd(list, OSINFO_ENTITY (os)); + } + + return FALSE; +} + +// Get me all OSes that 'upgrade' another OS (or whatever relationship is specified) +OsinfoOsList *osinfoUniqueValuesForOsRelationship(OsinfoDb *self, osinfoRelationship relshp, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_DB(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DB); + return NULL; + } + + if (!__osinfoCheckRelationshipValid(relshp)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_INVALID_RELATIONSHIP); + return NULL; + } + + // Create list + OsinfoOsList *newList = g_object_new(OSINFO_TYPE_OSLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + struct __osinfoOsCheckRelationshipArgs args = {OSINFO_LIST (newList), 0, err, relshp}; + + g_tree_foreach(self->priv->oses, __osinfoAddOsIfRelationship, &args); + if (args.errcode != 0) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), args.errcode, __osinfoErrorToString(args.errcode)); + g_object_unref(newList); + return NULL; + } + + return newList; +} + +/** PRIVATE */ + +void __osinfoAddDeviceToDb(OsinfoDb *db, OsinfoDevice *dev) +{ + gchar *id; + g_object_get(G_OBJECT(dev), "id", &id, NULL); + g_tree_insert(db->priv->devices, id, dev); +} + +void __osinfoAddHypervisorToDb(OsinfoDb *db, OsinfoHypervisor *hv) +{ + gchar *id; + g_object_get(G_OBJECT(hv), "id", &id, NULL); + g_tree_insert(db->priv->hypervisors, id, hv); +} + +void __osinfoAddOsToDb(OsinfoDb *db, OsinfoOs *os) +{ + gchar *id; + g_object_get(G_OBJECT(os), "id", &id, NULL); + g_tree_insert(db->priv->oses, id, os); +} diff --git a/src/osinfo_device.c b/src/osinfo_device.c new file mode 100644 index 0000000..cae6f1b --- /dev/null +++ b/src/osinfo_device.c @@ -0,0 +1,94 @@ +#include <osinfo.h> + +G_DEFINE_TYPE (OsinfoDevice, osinfo_device, OSINFO_TYPE_ENTITY); + +#define OSINFO_DEVICE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_DEVICE, OsinfoDevicePrivate)) + +static void osinfo_device_finalize (GObject *object); + +static void +osinfo_device_finalize (GObject *object) +{ + OsinfoDevice *self = OSINFO_DEVICE (object); + + /* Chain up to the parent class */ + G_OBJECT_CLASS (osinfo_device_parent_class)->finalize (object); +} + +/* Init functions */ +static void +osinfo_device_class_init (OsinfoDeviceClass *klass) +{ + GObjectClass *g_klass = G_OBJECT_CLASS (klass); + + g_klass->finalize = osinfo_device_finalize; + g_type_class_add_private (klass, sizeof (OsinfoDevicePrivate)); +} + +static void +osinfo_device_init (OsinfoDevice *self) +{ + OsinfoDevicePrivate *priv; + self->priv = priv = OSINFO_DEVICE_GET_PRIVATE(self); +} + +gchar *osinfoGetDeviceDriver(OsinfoDevice *self, + gchar *devType, + OsinfoOs *os, + OsinfoHypervisor *hv, + GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_DEVICE(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DEVICE); + return NULL; + } + + if (!OSINFO_IS_OS(os)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_OS); + return NULL; + } + + if (!OSINFO_IS_HYPERVISOR(hv)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_HV); + return NULL; + } + + if (!devType) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_DEVTYPE); + return NULL; + } + + gchar *driver = NULL; + + // For os, get hypervisor specific info. If not present, return NULL. + struct __osinfoHvSection *hvSection = NULL; + hvSection = g_tree_lookup(os->priv->hypervisors, (OSINFO_ENTITY(hv))->priv->id); + if (!hvSection) + return NULL; + + // Check for info for type of devices in <os,hv>. If not found, return NULL. + GTree *section = NULL; + section = g_tree_lookup(hvSection->sections, devType); + if (!section) + return NULL; + + // Check device section for device. If not found, return NULL. + struct __osinfoDeviceLink *deviceLink = NULL; + deviceLink = g_tree_lookup(section, (OSINFO_ENTITY(self))->priv->id); + if (!deviceLink) + return NULL; + + if (!deviceLink->driver) + return NULL; + + driver = g_strdup(deviceLink->driver); + if (!driver) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + return driver; +} diff --git a/src/osinfo_devicelist.c b/src/osinfo_devicelist.c new file mode 100644 index 0000000..db8a059 --- /dev/null +++ b/src/osinfo_devicelist.c @@ -0,0 +1,121 @@ +#include <osinfo.h> + +G_DEFINE_TYPE (OsinfoDeviceList, osinfo_devicelist, OSINFO_TYPE_LIST); + +#define OSINFO_DEVICELIST_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_DEVICELIST, OsinfoDeviceListPrivate)) + +static void osinfo_devicelist_finalize (GObject *object); + +struct _OsinfoDeviceListPrivate +{ + int tmp; +}; + +static void +osinfo_devicelist_finalize (GObject *object) +{ + /* Chain up to the parent class */ + G_OBJECT_CLASS (osinfo_devicelist_parent_class)->finalize (object); +} + +/* Init functions */ +static void +osinfo_devicelist_class_init (OsinfoDeviceListClass *klass) +{ + GObjectClass *g_klass = G_OBJECT_CLASS (klass); + + g_klass->finalize = osinfo_devicelist_finalize; + g_type_class_add_private (klass, sizeof (OsinfoDeviceListPrivate)); +} + +static void +osinfo_devicelist_init (OsinfoDeviceList *self) +{ + OsinfoDeviceListPrivate *priv; + self->priv = priv = OSINFO_DEVICELIST_GET_PRIVATE(self); + +} + +OsinfoDevice *osinfoGetDeviceAtIndex(OsinfoDeviceList *self, gint idx, GError **err) +{ + if (!OSINFO_IS_DEVICELIST(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DEVICELIST); + return NULL; + } + + OsinfoList *selfAsList = OSINFO_LIST (self); + OsinfoEntity *entity = osinfoGetEntityAtIndex(selfAsList, idx); + return OSINFO_DEVICE (entity); +} + +OsinfoDeviceList *osinfoDeviceListFilter(OsinfoDeviceList *self, OsinfoFilter *filter, GError **err) +{ + if (!OSINFO_IS_DEVICELIST(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DEVICELIST); + return NULL; + } + + if (filter && !OSINFO_IS_FILTER(filter)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + // For each element in self, if passes filter, add to new list. + OsinfoDeviceList *newList = g_object_new(OSINFO_TYPE_DEVICELIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + __osinfoDoFilter(OSINFO_LIST (self), OSINFO_LIST (newList), filter); + return newList; +} + +OsinfoDeviceList *osinfoDeviceListIntersect(OsinfoDeviceList *self, OsinfoDeviceList *otherList, GError **err) +{ + if (!OSINFO_IS_DEVICELIST(self) || !OSINFO_IS_DEVICELIST(otherList)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DEVICELIST); + return NULL; + } + + OsinfoDeviceList *newList = g_object_new(OSINFO_TYPE_DEVICELIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + + ret = __osinfoDoIntersect(self, otherList, newList); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} + +OsinfoDeviceList *osinfoDeviceListUnion(OsinfoDeviceList *self, OsinfoDeviceList *otherList, GError **err) +{ + if (!OSINFO_IS_DEVICELIST(self) || !OSINFO_IS_DEVICELIST(otherList)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_DEVICELIST); + return NULL; + } + + OsinfoDeviceList *newList = g_object_new(OSINFO_TYPE_DEVICELIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + ret = __osinfoDoUnion(self, otherList, newList); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} diff --git a/src/osinfo_entity.c b/src/osinfo_entity.c new file mode 100644 index 0000000..f052277 --- /dev/null +++ b/src/osinfo_entity.c @@ -0,0 +1,321 @@ +#include <osinfo.h> + +G_DEFINE_ABSTRACT_TYPE (OsinfoEntity, osinfo_entity, G_TYPE_OBJECT); + +#define OSINFO_ENTITY_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_ENTITY, OsinfoEntityPrivate)) + +static void osinfo_entity_finalize (GObject *object); + +enum OSI_ENTITY_PROPERTIES { + OSI_ENTITY_PROP_0, + + OSI_ENTITY_ID, + OSI_DB_PTR +}; + +static void +osinfo_entity_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + OsinfoEntity *self = OSINFO_ENTITY (object); + + switch (property_id) + { + case OSI_ENTITY_ID: + g_free(self->priv->id); + self->priv->id = g_value_dup_string (value); + break; + case OSI_DB_PTR: + self->priv->db = g_value_get_pointer (value); + break; + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +osinfo_entity_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + OsinfoEntity *self = OSINFO_ENTITY (object); + + switch (property_id) + { + case OSI_ENTITY_ID: + g_value_set_string (value, self->priv->id); + break; + case OSI_DB_PTR: + g_value_set_pointer(value, self->priv->db); + break; + default: + /* We don't have any other property... */ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +osinfo_entity_finalize (GObject *object) +{ + OsinfoEntity *self = OSINFO_ENTITY (object); + + g_free (self->priv->id); + g_tree_destroy (self->priv->params); + + /* Chain up to the parent class */ + G_OBJECT_CLASS (osinfo_entity_parent_class)->finalize (object); +} + +/* Init functions */ +static void +osinfo_entity_class_init (OsinfoEntityClass *klass) +{ + GObjectClass *g_klass = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + g_klass->set_property = osinfo_entity_set_property; + g_klass->get_property = osinfo_entity_get_property; + + pspec = g_param_spec_string ("id", + "ID", + "Contains unique identifier for entity.", + NULL /* default value */, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (g_klass, + OSI_ENTITY_ID, + pspec); + pspec = g_param_spec_pointer ("db", + "Db pointer", + "Contains backpointer to libosinfo db object.", + G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE); + g_object_class_install_property (g_klass, + OSI_DB_PTR, + pspec); + + g_klass->finalize = osinfo_entity_finalize; + g_type_class_add_private (klass, sizeof (OsinfoEntityPrivate)); +} + +static void +osinfo_entity_init (OsinfoEntity *self) +{ + OsinfoEntityPrivate *priv; + self->priv = priv = OSINFO_ENTITY_GET_PRIVATE(self); + + self->priv->params = g_tree_new_full(__osinfoStringCompare, NULL, g_free, __osinfoFreeParamVals); +} + +int __osinfoAddParam(OsinfoEntity *self, gchar *key, gchar *value) +{ + if (!OSINFO_IS_ENTITY(self) || !key || !value) + return -EINVAL; + + // First check if there exists an existing array of entries for this key + // If not, create a ptrarray of strings for this key and insert into map + gboolean found; + gpointer origKey, foundValue; + GPtrArray *valueArray; + gchar *valueDup = NULL, *keyDup = NULL; + + valueDup = g_strdup(value); + + if (!valueDup) + goto error_free; + + found = g_tree_lookup_extended(self->priv->params, key, &origKey, &foundValue); + if (!found) { + keyDup = g_strdup(key); + valueArray = g_ptr_array_new_with_free_func(g_free); + + if (!valueArray) + goto error_free; + if (!keyDup) { + g_ptr_array_free(valueArray, TRUE); + goto error_free; + } + + g_tree_insert(self->priv->params, keyDup, valueArray); + } + else + valueArray = (GPtrArray *) foundValue; + + // Add a copy of the value to the array + g_ptr_array_add(valueArray, valueDup); + return 0; + +error_free: + g_free(keyDup); + g_free(valueDup); + return -ENOMEM; +} + +void __osinfoClearParam(OsinfoEntity *self, gchar *key) +{ + g_tree_remove(self->priv->params, key); +} + +gboolean __osinfoGetKeys(gpointer key, gpointer value, gpointer data) +{ + struct __osinfoPtrArrayErr *arrayErr = (struct __osinfoPtrArrayErr *) data; + GPtrArray *results = arrayErr->array; + gchar *keyDup = g_strdup(key); + + if (!keyDup) { + arrayErr->err = -ENOMEM; + return TRUE; + } + g_ptr_array_add(results, keyDup); + return FALSE; // Continue iterating +} + +void __osinfoDupArray(gpointer data, gpointer user_data) +{ + struct __osinfoPtrArrayErr *arrayErr = (struct __osinfoPtrArrayErr *) data; + GPtrArray *results = arrayErr->array; + + if (arrayErr->err != 0) + return; + + gchar *valueDup = g_strdup((gchar *)data); + if (!valueDup) { + arrayErr->err = -ENOMEM; + return; + } + g_ptr_array_add(results, valueDup); +} + +gchar *osinfoGetId(OsinfoEntity *self, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_ENTITY(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_ENTITY); + return NULL; + } + + gchar *dupId = g_strdup(self->priv->id); + if (!dupId) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + return dupId; +} + +GPtrArray *osinfoGetParams(OsinfoEntity *self, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_ENTITY(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_ENTITY); + return NULL; + } + + GPtrArray *params = g_ptr_array_new(); + if (!params) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + struct __osinfoPtrArrayErr arrayErr = {params, 0}; + g_tree_foreach(self->priv->params, __osinfoGetKeys, &arrayErr); + + // If we had an error, cleanup and return NULL + if (arrayErr.err != 0) { + int i; + for (i = 0; i < params->len; i++) + g_free(g_ptr_array_index(params, i)); + g_ptr_array_free(params, TRUE); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), arrayErr.err, __osinfoErrorToString(arrayErr.err)); + return NULL; + } + + return params; +} + +gchar *osinfoGetParamValue(OsinfoEntity *self, gchar *key, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_ENTITY(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_ENTITY); + return NULL; + } + + if (!key) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_PROPNAME); + return NULL; + } + + gboolean found; + gpointer origKey, value; + gchar *firstValueDup; + GPtrArray *array; + + found = g_tree_lookup_extended(self->priv->params, key, &origKey, &value); + if (!found) + return NULL; + array = (GPtrArray *) value; + if (array->len == 0) + return NULL; + + firstValueDup = g_strdup(g_ptr_array_index(array, 0)); + if (!firstValueDup) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + return firstValueDup; +} + +GPtrArray *osinfoGetParamAllValues(OsinfoEntity *self, gchar *key, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_ENTITY(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_ENTITY); + return NULL; + } + + if (!key) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_PROPNAME); + return NULL; + } + + gboolean found; + gpointer origKey, value; + GPtrArray *srcArray, *retArray; + + retArray = g_ptr_array_new(); + if (!retArray) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + found = g_tree_lookup_extended(self->priv->params, key, &origKey, &value); + if (!found) + return retArray; + srcArray = (GPtrArray *) value; + if (srcArray->len == 0) + return retArray; + + struct __osinfoPtrArrayErr arrayErr = {retArray, 0}; + g_ptr_array_foreach(srcArray, __osinfoDupArray, &arrayErr); + if (arrayErr.err) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), arrayErr.err, __osinfoErrorToString(arrayErr.err)); + g_ptr_array_set_free_func(retArray, g_free); + g_ptr_array_free(retArray, TRUE); + return NULL; + } + + return retArray; +} diff --git a/src/osinfo_filter.c b/src/osinfo_filter.c new file mode 100644 index 0000000..fe65e45 --- /dev/null +++ b/src/osinfo_filter.c @@ -0,0 +1,298 @@ +#include <osinfo.h> + +G_DEFINE_TYPE (OsinfoFilter, osinfo_filter, G_TYPE_OBJECT); + +#define OSINFO_FILTER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_FILTER, OsinfoFilterPrivate)) + +static void osinfo_filter_finalize (GObject *object); + +static void +osinfo_filter_finalize (GObject *object) +{ + OsinfoFilter *self = OSINFO_FILTER (object); + + g_tree_destroy(self->priv->propertyConstraints); + g_tree_destroy(self->priv->relationshipConstraints); + + /* Chain up to the parent class */ + G_OBJECT_CLASS (osinfo_filter_parent_class)->finalize (object); +} + +/* Init functions */ +static void +osinfo_filter_class_init (OsinfoFilterClass *klass) +{ + GObjectClass *g_klass = G_OBJECT_CLASS (klass); + + g_klass->finalize = osinfo_filter_finalize; + g_type_class_add_private (klass, sizeof (OsinfoFilterPrivate)); +} + +static void +osinfo_filter_init (OsinfoFilter *self) +{ + OsinfoFilterPrivate *priv; + priv = OSINFO_FILTER_GET_PRIVATE(self); + self->priv = priv; + + self->priv->propertyConstraints = g_tree_new_full(__osinfoStringCompare, + NULL, + g_free, + __osinfoFreePtrArray); + + + self->priv->relationshipConstraints = g_tree_new_full(__osinfoIntCompare, + NULL, + NULL, + __osinfoFreePtrArray); +} + +void osinfoFreeFilter(OsinfoFilter *self) +{ + g_object_unref(self); +} + +gint osinfoAddFilterConstraint(OsinfoFilter *self, gchar *propName, gchar *propVal, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return -EINVAL; + + if (!OSINFO_IS_FILTER(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return -EINVAL; + } + + if (!propName) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_PROPNAME); + return -EINVAL; + } + + if (!propVal) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_PROPVAL); + return -EINVAL; + } + + // First check if there exists an array of entries for this key + // If not, create a ptrarray of strings for this key and insert into map + gboolean found; + gpointer origKey, foundValue; + GPtrArray *valueArray; + gchar *valueDup = NULL, *keyDup = NULL; + + valueDup = g_strdup(propVal); + + if (!valueDup) + goto error_free; + + found = g_tree_lookup_extended(self->priv->propertyConstraints, propName, &origKey, &foundValue); + if (!found) { + keyDup = g_strdup(propName); + valueArray = g_ptr_array_new_with_free_func(g_free); + + if (!valueArray) + goto error_free; + if (!keyDup) { + g_ptr_array_free(valueArray, TRUE); + goto error_free; + } + + g_tree_insert(self->priv->propertyConstraints, keyDup, valueArray); + } + else + valueArray = (GPtrArray *) foundValue; + + // Add a copy of the value to the array + g_ptr_array_add(valueArray, valueDup); + return 0; + +error_free: + g_free(keyDup); + g_free(valueDup); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return -ENOMEM; +} + +// Only applicable to OSes, ignored by other types of objects +gint osinfoAddRelationConstraint(OsinfoFilter *self, osinfoRelationship relshp, OsinfoOs *os, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return -EINVAL; + + if (!OSINFO_IS_FILTER(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return -EINVAL; + } + + if (!__osinfoCheckRelationshipValid(relshp)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_INVALID_RELATIONSHIP); + return -EINVAL; + } + + if (!OSINFO_IS_OS(os)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_OS); + return -EINVAL; + } + + // First check if there exists an array of entries for this key + // If not, create a ptrarray of strings for this key and insert into map + gboolean found; + gpointer origKey, foundValue; + GPtrArray *valueArray; + + found = g_tree_lookup_extended(self->priv->relationshipConstraints, (gpointer) relshp, &origKey, &foundValue); + if (!found) { + valueArray = g_ptr_array_new(); + if (!valueArray) + goto error_nomem; + + g_tree_insert(self->priv->relationshipConstraints, (gpointer) relshp, valueArray); + } + else + valueArray = (GPtrArray *) foundValue; + + // Add to the array + g_ptr_array_add(valueArray, os); + return 0; + +error_nomem: + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return -ENOMEM; +} + +void osinfoClearFilterConstraint(OsinfoFilter *self, gchar *propName) +{ + g_tree_remove(self->priv->propertyConstraints, propName); +} + +void osinfoClearRelationshipConstraint(OsinfoFilter *self, osinfoRelationship relshp) +{ + g_tree_remove(self->priv->relationshipConstraints, (gpointer) relshp); +} + +static gboolean __osinfoRemoveTreeEntry(gpointer key, gpointer value, gpointer data) +{ + GTree *tree = (GTree *) data; + g_tree_remove(tree, key); + return FALSE; // continue iterating +} + +void osinfoClearAllFilterConstraints(OsinfoFilter *self) +{ + g_tree_foreach(self->priv->propertyConstraints, __osinfoRemoveTreeEntry, self->priv->propertyConstraints); + g_tree_foreach(self->priv->relationshipConstraints, __osinfoRemoveTreeEntry, self->priv->relationshipConstraints); +} + +// get keyset for constraints map +GPtrArray *osinfoGetFilterConstraintKeys(OsinfoFilter *self, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_FILTER(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + GPtrArray *constraints = g_ptr_array_new(); + if (!constraints) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + struct __osinfoPtrArrayErr arrayErr = {constraints, 0}; + g_tree_foreach(self->priv->propertyConstraints, __osinfoGetKeys, &arrayErr); + + // If we had an error, cleanup and return NULL + if (arrayErr.err != 0) { + int i; + for (i = 0; i < constraints->len; i++) + g_free(g_ptr_array_index(constraints, i)); + g_ptr_array_free(constraints, TRUE); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), arrayErr.err, __osinfoErrorToString(arrayErr.err)); + return NULL; + } + + return constraints; +} + +// get values for given key +GPtrArray *osinfoGetFilterConstraintValues(OsinfoFilter *self, gchar *propName, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_FILTER(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + if (!propName) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_PROPNAME); + return NULL; + } + + gboolean found; + gpointer origKey, value; + GPtrArray *srcArray, *retArray; + + retArray = g_ptr_array_new(); + if (!retArray) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + found = g_tree_lookup_extended(self->priv->propertyConstraints, propName, &origKey, &value); + if (!found) + return retArray; + srcArray = (GPtrArray *) value; + if (srcArray->len == 0) + return retArray; + + struct __osinfoPtrArrayErr arrayErr = {retArray, 0}; + g_ptr_array_foreach(srcArray, __osinfoDupArray, &arrayErr); + if (arrayErr.err) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), arrayErr.err, __osinfoErrorToString(arrayErr.err)); + g_ptr_array_set_free_func(retArray, g_free); + g_ptr_array_free(retArray, TRUE); + return NULL; + } + + return retArray; +} + +// get oses for given relshp +OsinfoOsList *osinfoGetRelationshipConstraintValue(OsinfoFilter *self, osinfoRelationship relshp, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_FILTER(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + if (!__osinfoCheckRelationshipValid(relshp)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_INVALID_RELATIONSHIP); + return NULL; + } + + // Create our list + OsinfoOsList *newList = g_object_new(OSINFO_TYPE_OSLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + GPtrArray *relatedOses = NULL; + relatedOses = g_tree_lookup(self->priv->relationshipConstraints, (gpointer) relshp); + if (relatedOses) { + int i, len; + len = relatedOses->len; + for (i = 0; i < len; i++) { + OsinfoOs *os = g_ptr_array_index(relatedOses, i); + __osinfoListAdd(OSINFO_LIST (newList), OSINFO_ENTITY (os)); + } + } + + return newList; +} diff --git a/src/osinfo_hypervisor.c b/src/osinfo_hypervisor.c new file mode 100644 index 0000000..30eb445 --- /dev/null +++ b/src/osinfo_hypervisor.c @@ -0,0 +1,122 @@ +#include <osinfo.h> + +G_DEFINE_TYPE (OsinfoHypervisor, osinfo_hypervisor, OSINFO_TYPE_ENTITY); + +#define OSINFO_HYPERVISOR_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_HYPERVISOR, OsinfoHypervisorPrivate)) + +static void osinfo_hypervisor_finalize (GObject *object); + +static void +osinfo_hypervisor_finalize (GObject *object) +{ + OsinfoHypervisor *self = OSINFO_HYPERVISOR (object); + + g_tree_destroy (self->priv->sections); + g_tree_destroy (self->priv->sectionsAsList); + + /* Chain up to the parent class */ + G_OBJECT_CLASS (osinfo_hypervisor_parent_class)->finalize (object); +} + +/* Init functions */ +static void +osinfo_hypervisor_class_init (OsinfoHypervisorClass *klass) +{ + GObjectClass *g_klass = G_OBJECT_CLASS (klass); + + g_klass->finalize = osinfo_hypervisor_finalize; + g_type_class_add_private (klass, sizeof (OsinfoHypervisorPrivate)); +} + +static void +osinfo_hypervisor_init (OsinfoHypervisor *self) +{ + OsinfoHypervisorPrivate *priv; + self->priv = priv = OSINFO_HYPERVISOR_GET_PRIVATE(self); + + self->priv->sections = g_tree_new_full(__osinfoStringCompare, NULL, g_free, __osinfoFreeDeviceSection); + self->priv->sectionsAsList = g_tree_new_full(__osinfoStringCompare, NULL, g_free, __osinfoFreePtrArray); +} + +int __osinfoAddDeviceToSectionHv(OsinfoHypervisor *self, gchar *section, gchar *id, gchar *driver) +{ + if( !OSINFO_IS_HYPERVISOR(self) || !section || !id || !driver) + return -EINVAL; + + return __osinfoAddDeviceToSection(self->priv->sections, self->priv->sectionsAsList, section, id, driver); +} + +void __osinfoClearDeviceSectionHv(OsinfoHypervisor *self, gchar *section) +{ + if (!OSINFO_IS_HYPERVISOR(self) || !section) + return; + + __osinfoClearDeviceSection(self->priv->sections, self->priv->sectionsAsList, section); +} + +GPtrArray *osinfoGetHypervisorDeviceTypes(OsinfoHypervisor *self, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_HYPERVISOR(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_HV); + return NULL; + } + + GPtrArray *deviceTypes = g_ptr_array_sized_new(g_tree_nnodes(self->priv->sections)); + if (!deviceTypes) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + // For each key in our tree of device sections, dup and add to the array + struct __osinfoPtrArrayErr arrayErr = {deviceTypes, 0}; + g_tree_foreach(self->priv->sections, __osinfoGetKeys, &arrayErr); + return deviceTypes; +} + +OsinfoDeviceList *osinfoGetHypervisorDevicesByType(OsinfoHypervisor *self, gchar *devType, OsinfoFilter *filter, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_HYPERVISOR(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_HV); + return NULL; + } + + if (filter && !OSINFO_IS_FILTER(filter)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + if (!devType) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_DEVTYPE); + return NULL; + } + + // Create our device list + OsinfoDeviceList *newList = g_object_new(OSINFO_TYPE_DEVICELIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + // If section does not exist, return empty list + GPtrArray *sectionList = NULL; + sectionList = g_tree_lookup(self->priv->sectionsAsList, devType); + if (!sectionList) + return newList; + + // For each device in section list, apply filter. If filter passes, add device to list. + int i; + struct __osinfoDeviceLink *deviceLink; + for (i = 0; i < sectionList->len; i++) { + deviceLink = g_ptr_array_index(sectionList, i); + if (__osinfoDevicePassesFilter(filter, deviceLink->dev)) + __osinfoListAdd(OSINFO_LIST (newList), OSINFO_ENTITY (deviceLink->dev)); + } + + return newList; +} diff --git a/src/osinfo_hypervisorlist.c b/src/osinfo_hypervisorlist.c new file mode 100644 index 0000000..be42df7 --- /dev/null +++ b/src/osinfo_hypervisorlist.c @@ -0,0 +1,121 @@ +#include <osinfo.h> + +G_DEFINE_TYPE (OsinfoHypervisorList, osinfo_hypervisorlist, OSINFO_TYPE_LIST); + +#define OSINFO_HYPERVISORLIST_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_HYPERVISORLIST, OsinfoHypervisorListPrivate)) + +static void osinfo_hypervisorlist_finalize (GObject *object); + +struct _OsinfoHypervisorListPrivate +{ + int tmp; +}; + +static void +osinfo_hypervisorlist_finalize (GObject *object) +{ + /* Chain up to the parent class */ + G_OBJECT_CLASS (osinfo_hypervisorlist_parent_class)->finalize (object); +} + +/* Init functions */ +static void +osinfo_hypervisorlist_class_init (OsinfoHypervisorListClass *klass) +{ + GObjectClass *g_klass = G_OBJECT_CLASS (klass); + + g_klass->finalize = osinfo_hypervisorlist_finalize; + g_type_class_add_private (klass, sizeof (OsinfoHypervisorListPrivate)); +} + +static void +osinfo_hypervisorlist_init (OsinfoHypervisorList *self) +{ + OsinfoHypervisorListPrivate *priv; + self->priv = priv = OSINFO_HYPERVISORLIST_GET_PRIVATE(self); + +} + +OsinfoHypervisor *osinfoGetHypervisorAtIndex(OsinfoHypervisorList *self, gint idx, GError **err) +{ + if (!OSINFO_IS_HYPERVISORLIST(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_HYPERVISORLIST); + return NULL; + } + + OsinfoList *selfAsList = OSINFO_LIST (self); + OsinfoEntity *entity = osinfoGetEntityAtIndex(selfAsList, idx); + return OSINFO_HYPERVISOR (entity); +} + +OsinfoHypervisorList *osinfoHypervisorListFilter(OsinfoHypervisorList *self, OsinfoFilter *filter, GError **err) +{ + if (!OSINFO_IS_HYPERVISORLIST(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_HYPERVISORLIST); + return NULL; + } + + if (filter && !OSINFO_IS_FILTER(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + // For each element in self, if passes filter, add to new list. + OsinfoHypervisorList *newList = g_object_new(OSINFO_TYPE_HYPERVISORLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + __osinfoDoFilter(OSINFO_LIST (self), OSINFO_LIST (newList), filter); + return newList; +} + +OsinfoHypervisorList *osinfoHypervisorListIntersect(OsinfoHypervisorList *self, OsinfoHypervisorList *otherList, GError **err) +{ + if (!OSINFO_IS_HYPERVISORLIST(self) || !OSINFO_IS_HYPERVISORLIST(otherList)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_HYPERVISORLIST); + return NULL; + } + + OsinfoHypervisorList *newList = g_object_new(OSINFO_TYPE_HYPERVISORLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + + ret = __osinfoDoIntersect(self, otherList, newList); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} + +OsinfoHypervisorList *osinfoHypervisorListUnion(OsinfoHypervisorList *self, OsinfoHypervisorList *otherList, GError **err) +{ + if (!OSINFO_IS_HYPERVISORLIST(self) || !OSINFO_IS_HYPERVISORLIST(otherList)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_HYPERVISORLIST); + return NULL; + } + + OsinfoHypervisorList *newList = g_object_new(OSINFO_TYPE_HYPERVISORLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + ret = __osinfoDoUnion(self, otherList, newList); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} diff --git a/src/osinfo_list.c b/src/osinfo_list.c new file mode 100644 index 0000000..964e01d --- /dev/null +++ b/src/osinfo_list.c @@ -0,0 +1,219 @@ +#include <osinfo.h> + +G_DEFINE_TYPE (OsinfoList, osinfo_list, G_TYPE_OBJECT); + +#define OSINFO_LIST_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_LIST, OsinfoListPrivate)) + +static void osinfo_list_finalize (GObject *object); + +struct _OsinfoListPrivate +{ + GPtrArray *array; +}; + +static void +osinfo_list_finalize (GObject *object) +{ + OsinfoList *self = OSINFO_LIST (object); + + g_ptr_array_free(self->priv->array, TRUE); + + /* Chain up to the parent class */ + G_OBJECT_CLASS (osinfo_list_parent_class)->finalize (object); +} + +/* Init functions */ +static void +osinfo_list_class_init (OsinfoListClass *klass) +{ + GObjectClass *g_klass = G_OBJECT_CLASS (klass); + + g_klass->finalize = osinfo_list_finalize; + g_type_class_add_private (klass, sizeof (OsinfoListPrivate)); +} + +static void +osinfo_list_init (OsinfoList *self) +{ + OsinfoListPrivate *priv; + self->priv = priv = OSINFO_LIST_GET_PRIVATE(self); + + self->priv->array = g_ptr_array_new(); +} + +void osinfoFreeList(OsinfoList *self) +{ + g_object_unref(self); +} + +gint osinfoListLength(OsinfoList *self) +{ + return self->priv->array->len; +} + +OsinfoEntity *osinfoGetEntityAtIndex(OsinfoList *self, gint idx) +{ + return g_ptr_array_index(self->priv->array, idx); +} + +void __osinfoListAdd(OsinfoList *self, OsinfoEntity *entity) +{ + g_ptr_array_add(self->priv->array, entity); +} + +void __osinfoDoFilter(OsinfoList *src, OsinfoList *dst, OsinfoFilter *filter) +{ + int i, len; + len = osinfoListLength(src); + for (i = 0; i < len; i++) { + OsinfoEntity *entity = osinfoGetEntityAtIndex(src, i); + if (__osinfoEntityPassesFilter(filter, entity)) + __osinfoListAdd(dst, entity); + } +} + +OsinfoList *osinfoListFilter(OsinfoList *self, OsinfoFilter *filter, GError **err) +{ + if (!OSINFO_IS_LIST(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_LIST); + return NULL; + } + + if (filter && !OSINFO_IS_FILTER(filter)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + // For each element in self, if passes filter, add to new list. + OsinfoList *newList = g_object_new(OSINFO_TYPE_LIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + __osinfoDoFilter(self, newList, filter); + return newList; +} + +int __osinfoDoIntersect(OsinfoList *src1, OsinfoList *src2, OsinfoList *dst) +{ + int i, len; + + // Make set representation of otherList and newList + GTree *otherSet = g_tree_new(__osinfoStringCompareBase); + if (!otherSet) + return -ENOMEM; + + GTree *newSet = g_tree_new(__osinfoStringCompareBase); + if (!newSet) { + g_tree_destroy(otherSet); + return -ENOMEM; + } + + // Add all from otherList to otherSet + len = osinfoListLength(src2); + for (i = 0; i < len; i++) { + OsinfoEntity *entity = osinfoGetEntityAtIndex(src2, i); + gchar *id = entity->priv->id; + g_tree_insert(otherSet, id, entity); + } + + // If other contains entity, and new list does not, add to new list + len = osinfoListLength(src1); + for (i = 0; i < len; i++) { + OsinfoEntity *entity = osinfoGetEntityAtIndex(src1, i); + gchar *id = entity->priv->id; + + if (g_tree_lookup(otherSet, entity->priv->id) && + !g_tree_lookup(newSet, entity->priv->id)) { + g_tree_insert(newSet, id, entity); + __osinfoListAdd(dst, entity); + } + } + + g_tree_destroy(otherSet); + g_tree_destroy(newSet); + return 0; +} + +OsinfoList *osinfoListIntersect(OsinfoList *self, OsinfoList *otherList, GError **err) +{ + if (!OSINFO_IS_LIST(self) || !OSINFO_IS_LIST(otherList)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_LIST); + return NULL; + } + + OsinfoList *newList = g_object_new(OSINFO_TYPE_LIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + + ret = __osinfoDoIntersect(self, otherList, newList); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} + +int __osinfoDoUnion(OsinfoList *src1, OsinfoList *src2, OsinfoList *dst) +{ + // Make set version of new list + GTree *newSet = g_tree_new(__osinfoStringCompareBase); + if (!newSet) + return -ENOMEM; + + // Add all from other list to new list + int i, len; + len = osinfoListLength(src2); + for (i = 0; i < len; i++) { + OsinfoEntity *entity = osinfoGetEntityAtIndex(src2, i); + gchar *id = entity->priv->id; + __osinfoListAdd(dst, entity); + g_tree_insert(newSet, id, entity); + } + + // Add remaining elements from this list to new list + len = osinfoListLength(src1); + for (i = 0; i < len; i++) { + OsinfoEntity *entity = osinfoGetEntityAtIndex(src1, i); + gchar *id = entity->priv->id; + // If new list does not contain element, add to new list + if (!g_tree_lookup(newSet, id)) { + __osinfoListAdd(dst, entity); + g_tree_insert(newSet, id, entity); + } + } + + g_tree_destroy(newSet); + return 0; +} + +OsinfoList *osinfoListUnion(OsinfoList *self, OsinfoList *otherList, GError **err) +{ + if (!OSINFO_IS_LIST(self) || !OSINFO_IS_LIST(otherList)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_LIST); + return NULL; + } + + OsinfoList *newList = g_object_new(OSINFO_TYPE_LIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + ret = __osinfoDoUnion(self, otherList, newList); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} diff --git a/src/osinfo_os.c b/src/osinfo_os.c new file mode 100644 index 0000000..db02271 --- /dev/null +++ b/src/osinfo_os.c @@ -0,0 +1,402 @@ +#include <osinfo.h> + +G_DEFINE_TYPE (OsinfoOs, osinfo_os, OSINFO_TYPE_ENTITY); + +#define OSINFO_OS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_OS, OsinfoOsPrivate)) + +static void osinfo_os_finalize (GObject *object); + +static void +osinfo_os_finalize (GObject *object) +{ + OsinfoOs *self = OSINFO_OS (object); + + g_tree_destroy (self->priv->sections); + g_tree_destroy (self->priv->sectionsAsList); + g_tree_destroy (self->priv->hypervisors); + g_tree_destroy (self->priv->relationshipsByOs); + g_tree_destroy (self->priv->relationshipsByType); + + /* Chain up to the parent class */ + G_OBJECT_CLASS (osinfo_os_parent_class)->finalize (object); +} + +/* Init functions */ +static void +osinfo_os_class_init (OsinfoOsClass *klass) +{ + GObjectClass *g_klass = G_OBJECT_CLASS (klass); + + g_klass->finalize = osinfo_os_finalize; + g_type_class_add_private (klass, sizeof (OsinfoOsPrivate)); +} + +static void +osinfo_os_init (OsinfoOs *self) +{ + OsinfoOsPrivate *priv; + self->priv = priv = OSINFO_OS_GET_PRIVATE(self); + + self->priv->sections = g_tree_new_full(__osinfoStringCompare, + NULL, + g_free, + __osinfoFreeDeviceSection); + + self->priv->sectionsAsList = g_tree_new_full(__osinfoStringCompare, + NULL, + g_free, + __osinfoFreePtrArray); + + self->priv->relationshipsByOs = g_tree_new_full(__osinfoStringCompare, + NULL, + g_free, + __osinfoFreeRelationship); + self->priv->relationshipsByType = g_tree_new(__osinfoIntCompareBase); + + self->priv->hypervisors = g_tree_new_full(__osinfoStringCompare, + NULL, + g_free, + __osinfoFreeHvSection); +} + +static int __osinfoAddOsRelationshipByOs(OsinfoOs *self, + gchar *otherOsId, + osinfoRelationship rel, + struct __osinfoOsLink *osLink) +{ + gboolean found; + gpointer origKey, foundValue; + GPtrArray *relationshipsForOs; + gchar *otherOsIdDup = NULL; + + found = g_tree_lookup_extended(self->priv->relationshipsByOs, otherOsId, &origKey, &foundValue); + if (!found) { + otherOsIdDup = g_strdup(otherOsId); + relationshipsForOs = g_ptr_array_new_with_free_func(__osinfoFreeOsLink); + + if (!relationshipsForOs) + return -ENOMEM; + if (!otherOsIdDup) { + g_ptr_array_free(relationshipsForOs, TRUE); + return -ENOMEM; + } + g_tree_insert(self->priv->relationshipsByOs, otherOsIdDup, relationshipsForOs); + } + else + relationshipsForOs = (GPtrArray *) foundValue; + + g_ptr_array_add(relationshipsForOs, osLink); + return 0; +} + +static int __osinfoAddOsRelationshipByType(OsinfoOs *self, + osinfoRelationship relshp, + struct __osinfoOsLink *osLink) +{ + gboolean found; + gpointer origKey, foundValue; + GPtrArray *relationshipsForType; + + found = g_tree_lookup_extended(self->priv->relationshipsByType, (gpointer) relshp, &origKey, &foundValue); + if (!found) { + relationshipsForType = g_ptr_array_new(); + if (!relationshipsForType) + return -ENOMEM; + + g_tree_insert(self->priv->relationshipsByType, (gpointer) relshp, relationshipsForType); + } + else + relationshipsForType = (GPtrArray *) foundValue; + + g_ptr_array_add(relationshipsForType, osLink); + return 0; +} + +static void __osinfoRemoveOsLink(OsinfoOs *self, + gchar *otherOsId, + osinfoRelationship relshp, + struct __osinfoOsLink *osLink) +{ + gboolean found; + gpointer origKey, foundValue; + GPtrArray *relationshipsForOs; + GPtrArray *relationshipsForType; + + // First from by-os list + found = g_tree_lookup_extended(self->priv->relationshipsByOs, otherOsId, &origKey, &foundValue); + if (found) { + relationshipsForOs = (GPtrArray *) foundValue; + g_ptr_array_remove(relationshipsForOs, osLink); + } + + // Now from by-relshp list + found = g_tree_lookup_extended(self->priv->relationshipsByType, (gpointer) relshp, &origKey, &foundValue); + if (found) { + relationshipsForType = (GPtrArray *) foundValue; + g_ptr_array_remove(relationshipsForType, osLink); + } +} + +int __osinfoAddOsRelationship (OsinfoOs *self, gchar *otherOsId, osinfoRelationship rel) +{ + if ( !OSINFO_IS_OS(self) || !otherOsId) + return -EINVAL; + + struct __osinfoOsLink *osLink = NULL; + osLink = g_malloc(sizeof(*osLink)); + if (!osLink) + return -ENOMEM; + + osLink->subjectOs = self; + osLink->verb = rel; + + int ret; + ret = __osinfoAddOsRelationshipByOs(self, otherOsId, rel, osLink); + if (ret != 0) + goto error_free; + + ret = __osinfoAddOsRelationshipByType(self, rel, osLink); + if (ret != 0) + goto error_cleanup; + + return ret; + +error_cleanup: + __osinfoRemoveOsLink(self, otherOsId, rel, osLink); +error_free: + g_free(osLink); + return ret; +} + +int __osinfoAddDeviceToSectionOs(OsinfoOs *self, gchar *section, gchar *id, gchar *driver) +{ + if( !OSINFO_IS_OS(self) || !section || !id || !driver) + return -EINVAL; + + return __osinfoAddDeviceToSection(self->priv->sections, self->priv->sectionsAsList, section, id, driver); +} + +void __osinfoClearDeviceSectionOs(OsinfoOs *self, gchar *section) +{ + if (!OSINFO_IS_OS(self) || !section) + return; + + __osinfoClearDeviceSection(self->priv->sections, self->priv->sectionsAsList, section); +} + +struct __osinfoHvSection *__osinfoAddHypervisorSectionToOs(OsinfoOs *self, gchar *hvId) +{ + if (!OSINFO_IS_OS(self) || !hvId) + return NULL; + + gboolean found; + gpointer origKey, foundValue; + struct __osinfoHvSection *hvSection = NULL; + gchar *hvIdDup = NULL; + GTree *deviceSections; + GTree *deviceSectionsAsList; + + found = g_tree_lookup_extended(self->priv->hypervisors, hvId, &origKey, &foundValue); + if (!found) { + hvSection = g_malloc(sizeof(*hvSection)); + hvIdDup = g_strdup(hvId); + deviceSections = g_tree_new_full(__osinfoStringCompare, + NULL, + g_free, + __osinfoFreeDeviceSection); + + if (!deviceSections) + goto error_free; + + deviceSectionsAsList = g_tree_new_full(__osinfoStringCompare, + NULL, + g_free, + __osinfoFreePtrArray); + if (!deviceSectionsAsList) { + g_tree_destroy(deviceSections); + goto error_free; + } + + if (!hvSection || !hvIdDup) { + g_tree_destroy(deviceSectionsAsList); + g_tree_destroy(deviceSections); + goto error_free; + } + + hvSection->os = self; + // Will set hv link later + hvSection->sections = deviceSections; + hvSection->sectionsAsList = deviceSectionsAsList; + + g_tree_insert(self->priv->hypervisors, hvIdDup, hvSection); + return hvSection; + } + else + return (struct __osinfoHvSection *) foundValue; + +error_free: + g_free(hvSection); + g_free(hvIdDup); + return NULL; +} + +void __osinfoRemoveHvSectionFromOs(OsinfoOs *self, gchar *hvId) +{ + g_tree_remove(self->priv->hypervisors, hvId); +} + +OsinfoDevice *osinfoGetPreferredDeviceForOs(OsinfoOs *self, OsinfoHypervisor *hv, gchar *devType, OsinfoFilter *filter, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_OS(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_OS); + return NULL; + } + + if (hv && !OSINFO_IS_HYPERVISOR(hv)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_HV); + return NULL; + } + + if (!devType) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_DEVTYPE); + return NULL; + } + + if (filter && !OSINFO_IS_FILTER(filter)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + // Check if device type info present for <os,hv>, else return NULL. + + GPtrArray *sectionList = NULL; + if (hv) { + // Check if hypervisor specific info present for Os, else return NULL. + struct __osinfoHvSection *hvSection = NULL; + hvSection = g_tree_lookup(self->priv->hypervisors, (OSINFO_ENTITY(hv))->priv->id); + if (!hvSection) + return NULL; + + sectionList = g_tree_lookup(hvSection->sectionsAsList, devType); + if (!sectionList) + return NULL; + } + else { + sectionList = g_tree_lookup(self->priv->sectionsAsList, devType); + if (!sectionList) + return NULL; + } + + // For each device in section list, apply filter. If filter passes, return device. + int i; + struct __osinfoDeviceLink *deviceLink; + for (i = 0; i < sectionList->len; i++) { + deviceLink = g_ptr_array_index(sectionList, i); + if (__osinfoDevicePassesFilter(filter, deviceLink->dev)) + return deviceLink->dev; + } + + // If no devices pass filter, return NULL. + return NULL; +} + +OsinfoOsList *osinfoGetRelatedOs(OsinfoOs *self, osinfoRelationship relshp, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_OS(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_OS); + return NULL; + } + + if (!__osinfoCheckRelationshipValid(relshp)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_INVALID_RELATIONSHIP); + return NULL; + } + + // Create our list + OsinfoOsList *newList = g_object_new(OSINFO_TYPE_OSLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + GPtrArray *relatedOses = NULL; + relatedOses = g_tree_lookup(self->priv->relationshipsByType, (gpointer) relshp); + if (relatedOses) { + int i, len; + len = relatedOses->len; + for (i = 0; i < len; i++) { + struct __osinfoOsLink *osLink = g_ptr_array_index(relatedOses, i); + __osinfoListAdd(OSINFO_LIST (newList), OSINFO_ENTITY (osLink->directObjectOs)); + } + } + + return newList; +} + +OsinfoDeviceList *osinfoGetDevicesForOs(OsinfoOs *self, OsinfoHypervisor *hv, gchar *devType, OsinfoFilter *filter, GError **err) +{ + if (!__osinfoCheckGErrorParamValid(err)) + return NULL; + + if (!OSINFO_IS_OS(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_OS); + return NULL; + } + + if (!OSINFO_IS_HYPERVISOR(hv)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_HV); + return NULL; + } + + if (!devType) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_NO_DEVTYPE); + return NULL; + } + + if (filter && !OSINFO_IS_FILTER(filter)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + GPtrArray *sectionList = NULL; + + // Create our device list + OsinfoDeviceList *newList = g_object_new(OSINFO_TYPE_DEVICELIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + if (hv) { + struct __osinfoHvSection *hvSection = NULL; + hvSection = g_tree_lookup(self->priv->hypervisors, (OSINFO_ENTITY(hv))->priv->id); + if (!hvSection) + return newList; + + sectionList = g_tree_lookup(hvSection->sectionsAsList, devType); + if (!sectionList) + return newList; + } + else { + sectionList = g_tree_lookup(self->priv->sectionsAsList, devType); + if (!sectionList) + return newList; + } + + // For each device in section list, apply filter. If filter passes, add device to list. + int i; + struct __osinfoDeviceLink *deviceLink; + for (i = 0; i < sectionList->len; i++) { + deviceLink = g_ptr_array_index(sectionList, i); + if (__osinfoDevicePassesFilter(filter, deviceLink->dev)) + __osinfoListAdd(OSINFO_LIST (newList), OSINFO_ENTITY (deviceLink->dev)); + } + + return NULL; +} diff --git a/src/osinfo_oslist.c b/src/osinfo_oslist.c new file mode 100644 index 0000000..d723703 --- /dev/null +++ b/src/osinfo_oslist.c @@ -0,0 +1,121 @@ +#include <osinfo.h> + +G_DEFINE_TYPE (OsinfoOsList, osinfo_oslist, OSINFO_TYPE_LIST); + +#define OSINFO_OSLIST_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), OSINFO_TYPE_OSLIST, OsinfoOsListPrivate)) + +static void osinfo_oslist_finalize (GObject *object); + +struct _OsinfoOsListPrivate +{ + int tmp; +}; + +static void +osinfo_oslist_finalize (GObject *object) +{ + /* Chain up to the parent class */ + G_OBJECT_CLASS (osinfo_oslist_parent_class)->finalize (object); +} + +/* Init functions */ +static void +osinfo_oslist_class_init (OsinfoOsListClass *klass) +{ + GObjectClass *g_klass = G_OBJECT_CLASS (klass); + + g_klass->finalize = osinfo_oslist_finalize; + g_type_class_add_private (klass, sizeof (OsinfoOsListPrivate)); +} + +static void +osinfo_oslist_init (OsinfoOsList *self) +{ + OsinfoOsListPrivate *priv; + self->priv = priv = OSINFO_OSLIST_GET_PRIVATE(self); + +} + +OsinfoOs *osinfoGetOsAtIndex(OsinfoOsList *self, gint idx, GError **err) +{ + if (!OSINFO_IS_OSLIST(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_OSLIST); + return NULL; + } + + OsinfoList *selfAsList = OSINFO_LIST (self); + OsinfoEntity *entity = osinfoGetEntityAtIndex(selfAsList, idx); + return OSINFO_OS (entity); +} + +OsinfoOsList *osinfoOsListFilter(OsinfoOsList *self, OsinfoFilter *filter, GError **err) +{ + if (!OSINFO_IS_OSLIST(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_OSLIST); + return NULL; + } + + if (filter && !OSINFO_IS_FILTER(self)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_FILTER); + return NULL; + } + + // For each element in self, if passes filter, add to new list. + OsinfoOsList *newList = g_object_new(OSINFO_TYPE_OSLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + __osinfoDoFilter(OSINFO_LIST (self), OSINFO_LIST (newList), filter); + return newList; +} + +OsinfoOsList *osinfoOsListIntersect(OsinfoOsList *self, OsinfoOsList *otherList, GError **err) +{ + if (!OSINFO_IS_OSLIST(self) || !OSINFO_IS_OSLIST(otherList)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_OSLIST); + return NULL; + } + + OsinfoOsList *newList = g_object_new(OSINFO_TYPE_OSLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + + ret = __osinfoDoIntersect(self, otherList, newList); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} + +OsinfoOsList *osinfoOsListUnion(OsinfoOsList *self, OsinfoOsList *otherList, GError **err) +{ + if (!OSINFO_IS_OSLIST(self) || !OSINFO_IS_OSLIST(otherList)) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -EINVAL, OSINFO_OBJ_NOT_OSLIST); + return NULL; + } + + OsinfoOsList *newList = g_object_new(OSINFO_TYPE_OSLIST, NULL); + if (!newList) { + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), -ENOMEM, OSINFO_NO_MEM); + return NULL; + } + + int ret; + ret = __osinfoDoUnion(self, otherList, newList); + if (ret != 0) { + g_object_unref(newList); + g_set_error_literal(err, g_quark_from_static_string("libosinfo"), ret, __osinfoErrorToString(ret)); + return NULL; + } + + return newList; +} |