summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/list.h238
-rw-r--r--src/osi_common.c364
-rw-r--r--src/osi_device.c675
-rw-r--r--src/osi_filter.c358
-rw-r--r--src/osi_hv.c396
-rw-r--r--src/osi_internal_types.h181
-rw-r--r--src/osi_lib.c328
-rw-r--r--src/osi_os.c738
-rw-r--r--src/osinfo_common.c349
-rw-r--r--src/osinfo_dataread.c (renamed from src/osi_dataread.c)468
-rw-r--r--src/osinfo_db.c555
-rw-r--r--src/osinfo_device.c94
-rw-r--r--src/osinfo_devicelist.c121
-rw-r--r--src/osinfo_entity.c321
-rw-r--r--src/osinfo_filter.c298
-rw-r--r--src/osinfo_hypervisor.c122
-rw-r--r--src/osinfo_hypervisorlist.c121
-rw-r--r--src/osinfo_list.c219
-rw-r--r--src/osinfo_os.c402
-rw-r--r--src/osinfo_oslist.c121
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, &section->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, &section->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(&section->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, &section->devices_list);
}
+ free(sectionType);
finished:
- list_add_tail(&section->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;
+}